如何构建一个多实例的systemd服务配置?

5

我正在尝试配置systemd以执行多个相同服务的实例,但似乎我做错了什么,文档资源也不太清楚。

创建了/lib/systemd/system/confluence@.service文件,内容如下:

[Unit]
Description=Confluence %i
After=postgresql.service nginx.service

[Service]
Type=forking
ExecStart=/opt/atlassian/confluence-%i/bin/start-confluence.sh
ExecStartPre=/opt/atlassian/confluence-%i/bin/setenv.sh prestart

ExecStop=/opt/atlassian/confluence-%i/bin/stop-confluence.sh

TimeoutStopSec=5min
PIDFile=/opt/atlassian/confluence-%i/work/catalina.pid

[Install]
WantedBy=multi-user.target

目前为止,情况很好,systemctl enable confluence.test 报告成功(是的,/opt/atlassian/confluence-test/中包含所需内容)。

但是,当我尝试使用 systemctl start confluence 启动服务时,我得到以下错误:

root@atlas:/lib/systemd/system# systemctl start confluence@test.service
Job for confluence@test.service failed. See "systemctl status confluence@test.service" and "journalctl -xe" for details.
root@atlas:/lib/systemd/system# systemctl status confluence@test.service
● confluence@test.service - Confluence test
   Loaded: loaded (/lib/systemd/system/confluence@.service; enabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Fri 2015-10-09 13:25:28 BST; 7s ago
  Process: 16352 ExecStartPre=/opt/atlassian/confluence-%i/bin/setenv.sh prestart (code=exited, status=203/EXEC)

Oct 09 13:25:28 atlas systemd[1]: Starting Confluence test...
Oct 09 13:25:28 atlas systemd[1]: confluence@test.service: control process exited, code=exited status=203
Oct 09 13:25:28 atlas systemd[1]: Failed to start Confluence test.
Oct 09 13:25:28 atlas systemd[1]: Unit confluence@test.service entered failed state.
Oct 09 13:25:28 atlas systemd[1]: confluence@test.service failed.

一些情况下,systemd似乎无法扩展"%i",而这本应该是实例名称。
2个回答

0

我一直在网上寻找需要创建自己的systemd单元、模板和目标文件所需的所有组件。这个问题是在搜索结果中的。在这种情况下,我认为我可以提供帮助,而不是寻求帮助。

我没有Confluence,并且不会安装它进行测试,因此我大部分时间都在猜测第一部分。

我认为问题在于%i说明符被转义了,可能会在命令中创建错误的路径。如果这就是整个问题,那么将其更改为未转义版本%I将是最简单的解决方案。然后,您的文件/lib/systemd/system/confluence@.service将变为:

[Unit]
Description=Confluence %I
After=postgresql.service nginx.service

[Service]
Type=forking
ExecStart=/opt/atlassian/confluence-%I/bin/start-confluence.sh
ExecStartPre=/opt/atlassian/confluence-%I/bin/setenv.sh prestart

ExecStop=/opt/atlassian/confluence-%I/bin/stop-confluence.sh

TimeoutStopSec=5min
PIDFile=/opt/atlassian/confluence-%I/work/catalina.pid

[Install]
WantedBy=multi-user.target

如果问题的根源不同,例如指定符号在命令中未扩展,则仍可以使用包装器脚本实现相同的结果。systemd应该消除它们的需要,但在新进程中使用旧系统通常导致理论与实践不符。
创建一个shell脚本,可能位于基础目录下。
使用以下内容创建/opt/atlassian/conflencectl:
#!/usr/bin/env bash
# Check that there is a command to execute
if ( ! test -n "$1" ) {
  exit 1
}

# Check that there is an instance name to use
if ( ! test -n "$2" ) {
  exit 1
}

# Make the directory name stub for this instance
InstanceDirName="confluence-$2"

# Execute the proper command, based on the command from the unit file
case $1 in
  Start)
    /opt/atlassian/$InstanceDirName/bin/start-confluence.sh;
    ;;
  StartPre )
    /opt/atlassian/$InstanceDirName/bin/setenv.sh prestart;
    ;;
  Stop )
    /opt/atlassian/$InstanceDirName/bin/stop-confluence.sh;
    ;;
  *)
    exit 1;
esac

根据操作需要或不需要的内容,您可以添加额外的安全、健全性或依赖性检查,例如测试目录或所需配置文件的存在。
然后您的systemd单元文件变成了:
[Unit]
Description=Confluence %I
After=postgresql.service nginx.service

[Service]
Type=forking
ExecStart=/opt/atlassian/conflencectl "Start" "%i"
ExecStartPre=/opt/atlassian/conflencectl "StartPre" "%i"

ExecStop=/opt/atlassian/conflencectl "Stop" "%i"

TimeoutStopSec=5min
PIDFile=/opt/atlassian/confluence-%I/work/catalina.pid

[Install]
WantedBy=multi-user.target

即使使用这个版本,我也不太确定PIDFile声明会发生什么,以及如何在需要时使用包装脚本进行补偿。我扫描过的文档似乎暗示着systemd已经非常擅长知道PID,因此可能并不需要它。然而,只有测试才能证明最终效果。

-1

每个实例都不能有单独的启动/停止脚本。

我建议使用ExecStart=/opt/atlassian/confluence/bin/start-confluence.sh

这将在每次调用时启动一个新的实例。

ExecStartPreExecStop也是如此。


2
根据同事的反馈,我认为这并不正确。他告诉我命令中只有第一个参数不支持变量扩展,这意味着使用/bin/bash或/bin/sh应该是实现此操作的替代方法。无论如何,我需要更多时间来找到可靠的生成新实例的方法。 - sorin
我同意。但是你会为每个实例拥有单独的脚本文件吗?相反,你可以将实例名称作为参数传递,并在脚本内部处理它。 - Thirupathi Thangavel
1
ExecStart=/opt/atlassian/confluence/bin/start-confluence.sh %i - Thirupathi Thangavel
1
不适用于Atlassian产品,因为几乎不可能像这样生成它们,需要为每个实例使用不同的目录(也需要为了能够并行运行不同的版本)。 - sorin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接