当所需单元第一次失败时,SystemD“Requires”失败

当所需单元第一次失败时,SystemD“Requires”失败

我创建了一个 SystemD 单元来启动一个服务,该服务需要另一个单元来预先启动。

我已经设置了依赖服务Requires=dependant.service,这样depending.service在启动过程中自动启动时,它首先尝试启动dependant.service

问题是,如果dependant.service开始得太早,它就无法开始(我不太确定这里的“太早”是什么意思)。为了解决这个问题,我设置dependant.serviceRestart=always.

而且工作正常 -depending.service启用并自动启动,它启动dependant.service,崩溃然后重新启动,并且在第二次尝试时总是成功启动。

depending.service已经看到了dependant.service第一次失败及其Requires=dependant.service失败的原因。日志显示:

systemd[1]: Dependency failed for depending.
systemd[1]: Job depending.service/start failed with result 'dependency'.

尽管dependant最终成功了,而且两者都Restart=alwaysdepending最初的失败后从未重新启动过dependant

我尝试了Requires=Wants=、和 的各种配置BindsTo=,但After未能找到导致重新启动depending后重新启动的组合dependant

答案1

看来根本原因是dependant.service有时启动得太早:添加Restart指令有点麻烦。对我来说,这表明它缺少时间要求,而这正是时间After要求。根据服务类型,您需要确定启动服务之前需要哪些资源。

假设这与网络相关,您需要在[Unit]部分添加以下内容dependant.service

After=network.target

通过这样做,您表明在 systemd 尝试启动服务之前基本网络应该可用。否则,systemd 将尝试并行启动尽可能多的服务,这意味着根据启动顺序,您可能会在基本上没有任何初始化的情况下启动,这种情况有些服务可以容忍,有些服务会严重失败。

如果您想确保depending.service始终以 重新启动dependant.service,请将 aBindsTo和添加Afterdepending.service

[Unit]
After=dependant.service
BindsTo=dependant.service

这些行为记录在systemd.unit(7)手册页。我很少需要使用超过Wants,RequiresAfter,但如果您的服务具有特别复杂的启动条件,则还有更高级的选项。

我发现在创建新服务(或服务组)时查看发行版提供的单元文件以了解它们是如何完成的并无耻地复制好的部分(尝试/usr/lib/systemd/system/lib/systemd/system)是很有帮助的:他们通常会找到关于什么的线索AfterRequires要求对于特定类型的服务有用。

答案2

对我来说BindsTo没有帮助。这是(我认为),因为BindsTo意味着依赖单元无法在没有依赖单元的情况下运行。但在这种情况下,由于从属单元第一次启动失败,因此从属进程尚未启动。

但根据systemd 单元的文档 PartOf每次重新启动后都会传播该事件。所以这对我有用:

[Unit]
After=dependant.service
PartOf=dependant.service

相关内容