systemd:服务依赖性“如果 A 没有运行,B 就不应该运行”?

systemd:服务依赖性“如果 A 没有运行,B 就不应该运行”?

(systemd 版本 229,仅供参考)

我有一个主服务 A 和一个辅助服务 B。主服务 A 可以自行运行。但服务 B 无法自行正确运行:它需要 A 运行(从技术上讲 B 可以运行,但我希望 systemd 阻止这种情况发生)。我的目标:如果 A 没有运行,B 也不应该运行。假设 A 和 B 正在运行,当 A 停止或死亡/崩溃时,B 也应该停止。

我如何实现这个目标?

我通过将 [Unit] 项目添加到 b.service 来接近,使用

Requisite=A.service
After=A.service

上述结果是

1) B won't start unless A is running (good).
2) B is stopped when A is stopped (good).
3) However, if I kill A, service B continues to run (bad).

我该如何修复最后的行为#3?我尝试使用 BindsTo 而不是 Requisite,就像在 B 的服务文件中这样:

BindsTo=A.service
After=A.service

我得到:

1) If A is not running and I start B, then A is also started
    (I want an error, I don't want A started)
2) B is stopped when A is stopped (good).
3) B is stopped when A is killed (good)

所以现在 #3 不错,但 #1 不是所需的行为。PartOf 和 BindsTo 似乎都不能解决问题,但也许我没有正确使用选项组合?从手册页中我不清楚哪些选项可以组合。

使用 BindsTo 时,我还尝试使用 ExecStartPre 使 B 的启动失败,但这当然不起作用,因为在启动 B 之前,B 的启动已经确定它需要运行 A(并启动了它)。

有没有办法在 Requisite 和 BindsTo 之间获得行为?我上面列出的 1-2-3?

提前感谢!

答案1

我也在寻找更优雅的解决方案。这里有一个开放的 systemd 票证,用于请求增强:https://github.com/systemd/systemd/issues/5966

目前我的解决方法如下:B.service

Requisite=A.service
After=A.service

A.服务

OnFailure=Stop-B.service

停止-B.服务

[Service]
Type=oneshot
TimeoutSec=0
ExecStart=/bin/systemctl stop B.service

答案2

我遇到了类似的情况需要解决。我想到的方法是创建一个目标单元作为障碍两种服务之间。

a.服务:

[Unit]
Wants=a.target

目标:

[Unit]
Requisite=a.service
After=a.service
PartOf=a.service
RefuseManualStart=true
RefuseManualStop=true

b.服务:

[Unit]
BindsTo=a.target
After=a.target

此设置产生了 OP 所需的行为,因为 a.target 始终与 a.service 一起处于活动状态(当 a.service 停止时,PartOf 会停止 a.target,RefuseManual* 避免在 a.target 上执行 systemctl start/stop 命令),并且 b.service 无法通过 a.target 启动 a.service。

答案3

我采用了与 Chris 类似的方法,但不需要创建单独的服务来停止 B:

B.服务

[Unit]
Requisite=A.service
After=A.service

A.服务

[Service]
ExecStopPost=/bin/systemctl stop B.service

B.service 中的那一Requisite行确保如果 A.service 尚未运行,则无法启动 B.service,而ExecStopPostA.service 中的那一行确保当 A.service 停止或处于非活动状态时,B.service 也会停止。

相关内容