是否可以编写一个当另一个服务启动时启动的 systemd 服务?

是否可以编写一个当另一个服务启动时启动的 systemd 服务?

这似乎应该是一个非常简单的问题,但我一直没能弄清楚。我有一个服务“Alice”:

[Unit]
Description=Alice
After=network.target

[Service]
Type=simple
Restart=on-failure
RestartSec=5
StartLimitInterval=0
ExecStart=sleep 30d

[Install]
WantedBy=multi-user.target

我想编写第二个服务 Bob,以便:

  • 当 Alice 成功启动时 Bob 开始启动
  • Bob 启动是因为,且仅仅因为 Alice 已成功启动(不是由系统启动或其他活动触发)
  • 当 Alice 停止时 Bob 也会停止

我希望在不修改 Alice 的情况下实现这一点。Alice 有时可能会随系统一起启动(通过systemctl enable alice.service),而在其他情况下则只能手动启动。实际上,将有 N 多个附加服务(Carol、Dave、Eve 等)具有自己的单元文件,所有这些服务都需要在 Alice 启动时启动,并且 N 可能会成为一个相当大的数字。

我尝试过各种 Unit 设置,例如 PartOf、BoundTo、Requires、After,到目前为止,我尝试过的任何组合都无法实现通过启动 Alice 来启动 Bob 的预期结果。我还发现,systemctl show bob.service在运行 后调用 会显示预期的设置systemctl daemon-reload,但反向设置(ConsistsOf、BoundBy、RequiredBy)不会显示在 中systemctl show alice.service,这显然违反了文档

在调用 daemon-reload 时或启动 Alice 时,我没有在系统日志中看到任何错误,这可以解释为什么 Bob 无法启动。

我可以做我想做的事吗?如果可以,我该如何解决此类问题?我正在 RHEL 8.7 和 systemd 239 上进行这些实验。

答案1

一个可能的答案。

到目前为止,似乎我无法为 Bob 配置任何配置,从而导致 Bob 在 Alice 启动时启动。因此,如果这是真的,那么我根本无法在不修改 Alice 的情况下做到这一点,但看起来我至少可以在不修改 alice.service 的情况下做到这一点。对我来说,这可能是一个足够的解决方案。

Bob 的单位部分:

[Unit]
Description=Bob
After=network.target
After=alice.service
PartOf=alice.service

然后我通过插入的方式修改 Alice,创建一个alice.service.requires/bob.service指向 bob.service 的符号链接。

到目前为止,这似乎正是我想要的——如果有理由避免这种方法,我还没有发现它们。虽然PartOf不会导致 Alice 在没有 Requires 符号链接的情况下启动 Bob,但它确实会导致 Bob 在 Alice 停止时停止(如果没有设置,就不会发生这种情况PartOf=alice.service)。

因此,最终 Bob 的安装程序例程(我正在开发的软件组件)将添加此步骤以在最后创建符号链接(Carol 等也将如此)。

编辑:我刚刚意识到 systemd 确实提供了这个功能,尽管我可能会用也可能不会用。我从 bob.service 中删除了WantedBy=multi-user.target[Install] 部分,并将其替换为 Alice:

[Install]
RequiredBy=alice.service

随后,我可以使用,systemctl enable bob.service因为它不会导致 Bob 在启动时启动,而只会在 Alice 启动时启动。它会在 /etc 下创建上述符号链接。(我的安装程序可能会在 /usr/lib 下手动执行此操作,而不是使用此机制。)

相关内容