【问题标题】:How to build a multi instance systemd service configuration?如何构建多实例 systemd 服务配置?
【发布时间】:2016-01-07 09:41:37
【问题描述】:

我正在尝试将 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”。

【问题讨论】:

    标签: systemd


    【解决方案1】:

    我一直在网上四处寻找我需要的片段来创建我自己的一组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,并且可能不需要它。然而,只有测试才能证明最终的效果。

    【讨论】:

      【解决方案2】:

      您不能为每个实例设置单独的启动/停止脚本。

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

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

      ExecStartPreExecStop 也是如此

      【讨论】:

      • 根据我从同事那里收到的反馈,我认为这并不正确。他告诉我,只有命令的第一个参数不支持变量扩展,这意味着使用 /bin/bash 或 /bin/sh 应该是实现这一点的替代方案。无论如何,我需要更多时间才能找到产生新实例的可靠方法。
      • 我同意。但是你会为每个实例有单独的脚本文件吗?相反,您可以将实例名称作为参数传递并在脚本中处理它。
      • ExecStart=/opt/atlassian/confluence/bin/start-confluence.sh %i 可以。
      • 不适用于 Atlassian 产品,因为几乎不可能像这样生成它们,每个实例需要不同的目录(也需要能够并行运行不同的版本)。
      猜你喜欢
      • 1970-01-01
      • 2021-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-21
      • 2015-05-23
      • 2020-03-16
      相关资源
      最近更新 更多