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
/Wants
或Conflicts
与多个其他单元一起使用。它们的所有依赖项将一起处理。然后,如果单元 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
上是一样的。