我创建了一个 SystemD 单元来启动一个服务,该服务需要另一个单元来预先启动。
我已经设置了依赖服务Requires=dependant.service
,这样depending.service
在启动过程中自动启动时,它首先尝试启动dependant.service
。
问题是,如果dependant.service
开始得太早,它就无法开始(我不太确定这里的“太早”是什么意思)。为了解决这个问题,我设置dependant.service
为Restart=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=always
在depending
最初的失败后从未重新启动过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
和添加After
到depending.service
:
[Unit]
After=dependant.service
BindsTo=dependant.service
这些行为记录在systemd.unit(7)
手册页。我很少需要使用超过Wants
,Requires
和After
,但如果您的服务具有特别复杂的启动条件,则还有更高级的选项。
我发现在创建新服务(或服务组)时查看发行版提供的单元文件以了解它们是如何完成的并无耻地复制好的部分(尝试/usr/lib/systemd/system
或/lib/systemd/system
)是很有帮助的:他们通常会找到关于什么的线索After
和Requires
要求对于特定类型的服务有用。
答案2
对我来说BindsTo
没有帮助。这是(我认为),因为BindsTo
意味着依赖单元无法在没有依赖单元的情况下运行。但在这种情况下,由于从属单元第一次启动失败,因此从属进程尚未启动。
但根据systemd 单元的文档 PartOf
每次重新启动后都会传播该事件。所以这对我有用:
[Unit]
After=dependant.service
PartOf=dependant.service