我总是遇到需要与服务 A 关联的程序在服务 B 之前运行完成的情况。“之后”并不能解决这个问题。之后说
最重要的是,对于服务单元,当所有配置的启动命令都已被调用并且它们要么失败或报告启动成功时,出于 Before=/After= 的目的,启动被认为已完成。”,但这并不意味着底层流程已成功完成。
在我看来,功能上有一个明显的漏洞。如果服务B依赖于服务A的成功完成,如何启动服务B?
我总是遇到需要与服务 A 关联的程序在服务 B 之前运行完成的情况。“之后”并不能解决这个问题。之后说
最重要的是,对于服务单元,当所有配置的启动命令都已被调用并且它们要么失败或报告启动成功时,出于 Before=/After= 的目的,启动被认为已完成。”,但这并不意味着底层流程已成功完成。
在我看来,功能上有一个明显的漏洞。如果服务B依赖于服务A的成功完成,如何启动服务B?
这个答案几乎清楚地回答了我的问题,但遗漏了 的相关描述
Type=oneshot
。以下是systemd.service 文档中的相关文本。因此,我们可以使用一次性服务来进行确定性排序。
这是
Requires=
您在使用时通常使用的固有解决方案After=
;引用man systemd.unit
:After=
只需指定您的单元相对于您所依赖的单元启动的时间点,并Requires=
定义您需要在该点成功启动其他单元。目标的问题是它会干扰关闭。这就是为什么你很难找到答案。如果
shutdown.target
被提升,那么你的服务将会停止,但是这会尝试触发你的后续服务。如果您的第一份工作是短期运行的,那么请考虑将它们组合成一个服务
Type=simple
,并使用 运行它ExecStartPre=
。系统将一直保留activating
到第一个作业完成为止,如果第一个作业成功,它只会执行第二个作业。如果第一个作业应该为第二个作业进行设置,则此样式非常有用。如果第二个作业也是短期运行,则使用
Type=oneshot
. 在这种情况下,两个工作都可以ExecStart=
。如果第一个作业不是短期运行的,但第二个作业是短期运行的,则考虑在
ExecStopPost=
. 但请务必小心,因为此命令无论是否ExecStart=
成功。$SERVICE_RESULT
您可以将第二个作业包装在脚本中,通过检查、$EXIT_CODE
和 来$EXIT_STATUS
根据第一个作业的成功情况有条件地运行它 。如果第二项工作是清理任务,则此范例特别有用。如果这两项工作都需要长时间运行,那么您需要发挥更多创意。您可以做的一件事是用一个单元设置一个触发器
*.path
。当被触摸时,这会触发它的姐妹服务PathChanged=
。对于路径,我将使用唯一的东西,并以说明符为前缀%t
来将此文件放入/run
:这不会干扰关闭,因为在触发下一个单元之前路径将停止。