如果另一个 systemd 服务正在运行,则阻止 systemd 服务启动

Ama*_*rus 5 job-control systemd systemd-service

在 systemd(UbuntuLinux 18.04 bionic 上的 v237)中,我可以创建一个服务文件(用于A.service),并指定另一个服务Requisite=B.service。这意味着如果我尝试启动A.serviceB.service尚未运行,则 A.service 将不会启动。这是 的弱版本,当我尝试启动时Requires它将启动。B.serviceA.service

\n\n

有相反的吗?我可以说\xe2\x80\x9c如果B.service正在运行,那么就不要启动这个服务\xe2\x80\x9d / \xe2\x80\x9c如果B.service正在运行,那么A.service无法启动\xe2\ x80\x9d?

\n\n

文档说如果我这样做Conflicts=B.service,那么启动A将停止 B 然后启动 A。但我不希望 B 停止,我只是希望 A 无法启动。我想要的东西就是Conflicts这样RequisiteRequires

\n\n

我可能可以将 更改ExecStart为会失败的 shell 命令systemctl is-active B.service或某种 hack。有没有合适的解决办法呢?

\n

小智 6

通常,执行此操作的方法是ExecStartPre检查其他服务是否正在运行。如果ExecStartPre命令返回错误代码,则启动过程的其余部分将中止。

ExecStartPre=/bin/bash -c '! /usr/bin/systemctl is-active --quiet other-unit.service'
Run Code Online (Sandbox Code Playgroud)


Thi*_*ado 6

后来我发现,这种情况的最佳选择是ExecCondition=因为它可以让你做适当的错误控制;ExecStartPre=如果以非零值退出,将始终生成错误;whileExecCondition=将允许停止执行而不抛出错误,或者在需要时抛出错误。这对于处理通知非常方便ExecStartPost=(您可以设置一个触发器来通知服务未启动,因为其他服务正在运行)。

ExecCondition= 在 ExecStartPre= 中的命令之前执行的可选命令。语法与 ExecStart= 相同,不同之处在于允许多个命令行,并且命令按顺序一个接一个地执行。

其行为类似于 ExecStartPre= 和条件检查混合:当 ExecCondition= 命令以退出代码 1 到 254(含)退出时,将跳过其余命令,并且单元不会标记为失败。然而,如果 ExecCondition= 命令以 255 或异常退出(例如超时、被信号终止等),则该单元将被视为失败(并且将跳过其余命令)。退出代码 0 或匹配 SuccessExitStatus= 的退出代码将继续执行下一个命令。

ExecStartPre= 中关于不运行长时间运行的进程的相同建议也适用于 ExecCondition=。ExecCondition= 还将运行 ExecStopPost= 中的命令,作为停止服务的一部分,以防出现任何非零或异常退出(如上所述)。

代码逻辑是一样的:

ExecCondition=/bin/bash -xc '/usr/bin/systemctl is-active --quiet other-unit.service && { [[ %i == "main" ]] && exit 255 || exit 1; } || exit 0'
Run Code Online (Sandbox Code Playgroud)

ExecCondition=over的优点ExecStartPre=是,在这个例子中,它会检查这个服务实例是否是“main”,并且会以失败的状态代码退出,因此您可以很容易地注意到它;ExecStartPost=您也可以用作和的触发器ExecStopPost=

一个建议是使用多个条目,而ExecCondition=不是在单个条目中运行太多命令(尽管允许);它将增强故障排除并防止由于超时而导致失败状态。