在一个命令中启动或停止多个服务时,systemctl 是否考虑服务依赖性?

在一个命令中启动或停止多个服务时,systemctl 是否考虑服务依赖性?

systemctl 允许在启动或停止命令中传递多个服务名称。

假设在 systemd 中,服务 A 配置为在服务 B 之前停止。当我现在执行时

systemctl stop B A

那么A和所有依赖的服务会先停止,然后B甚至B先在systemctl命令中传递吗?我的意思是 systemctl stop 中的服务名称顺序并未定义服务停止的顺序。

我进行了测试,它们证明了我的假设。但我想百分百确定这种方式始终有效。

答案1

并不真地!当前的代码不是那么聪明,它只是尝试停止/启动每个服务。

[它按照给定的顺序处理它们。它是一个小的虽然很聪明。由于某种原因(大概是性能原因),它不会在每一个之后等待,而只会在最后等待。所以它不像 那样工作systemctl start A; systemctl start B。它更接近systemctl start A & systemctl start B & wait。]

所以如果单元文件看起来像这样 -

# A.service
[Unit]
After=B.service

[Service]
Type=oneshot
ExecStart=/bin/sleep 2

# B.service
[Service]
Type=oneshot
ExecStart=/bin/sleep 2

systemctl start A B将启动 A 和 B。当前代码确实不是保证在启动 A 之前等待 B 完全启动。 [当前 A 和 B 将并行启动。] 你可以在journalctl

Mar 20 20:50:29 alan-laptop systemd[2007]: Starting A.service...
Mar 20 20:50:29 alan-laptop systemd[2007]: Starting B.service...
Mar 20 20:50:31 alan-laptop systemd[2007]: Started A.service.
Mar 20 20:50:31 alan-laptop systemd[2007]: Started B.service. 

然而,如果 A 和 B 在启动时被拉入初始事务,它们将按预期排序。

我认为可以使用 做一些事情来systemd-run创建和运行临时服务,该服务可以Requires/WantsConflicts与多个其他单元一起使用。它们的所有依赖项将一起处理。然后,如果单元 A 具有排序依赖性Before=After=对单元 B 具有排序依赖性,则将遵守该排序依赖性。

答案2

是的,你的假设是正确的。

当您在单个systemctl命令中启动或停止多个单元时,该命令将变成一个交易,因此系统管理器守护程序(也称为 PID 1)将尝试同时启动它们。

如果存在排序依赖项(使用Before=After=指令配置),则此时将考虑它们。

因此,如果您配置了在单元 B 之后启动单元 A 的顺序(文件A.service显示After=B.service),这意味着单元 A 将被停止单元 B (停止单元时顺序相反),那么这将按照您所描述的方式运行:依赖于 A 的单元将首先停止(因为当 A 停止时它们无法保持运行),然后停止 A,最后停止 B停了下来。

如果单元之间不存在顺序依赖性,则它们将被启动或停止在平行下。 (这意味着什么:systemd 仍然会按顺序处理它们,但它会用 SIGTERM 信号杀死进程,或者分叉一个进程来执行ExecStop=该单元的命令,但它会不等为了让主 PID 退出或者让ExecStop=命令完成,这就是“在平行下”在此上下文中的意思。由于信号是异步的并且分叉是非阻塞的,因此这非常接近真正的并行性,并且几乎所有效果都可以被认为是相同的。)

在大多数情况下,传递给 的单元的顺序systemctl并不重要(只有在非常极端的情况下,它的行为才会相同。)当存在显式的排序依赖性时,将受到尊重。如果没有,服务将并行启动/停止。

简而言之,systemctl stop B A本质systemctl stop A B上是一样的。

相关内容