例如,我有一些通常相互冲突的服务(相同的端口等)。但我从来不需要它们同时运行。例如,如果我启动 service a
,它会检查b
或是否c
正在运行并停止它们?如果其他服务未运行,则它会b
正常启动。但如果是的话,它会stop
向其他服务发送命令。
作为现在的解决方法,我只有一个 .sh 运行systemctl stop a.service
一个 while 循环,grepssystemctl status a.service
直到它返回停止,然后运行systemctl stop c.service
一个 while 循环,grepssystemctl status c.service
直到它返回停止。两者返回停止后,然后运行systemctl start b.service
。然后我制作了相同的文件,但用于启动a.service
和c.service
,但在我看来,这个解决方法相当混乱,我想知道是否有官方的东西。
答案1
冲突=
以空格分隔的单位名称列表。配置负面需求依赖性。如果一个单元在另一个单元上有 Conflicts= 设置,则启动前者将停止后者,反之亦然。
请注意,此设置并不意味着排序依赖关系,类似于上面描述的 Wants= 和 Requires= 依赖关系。这意味着,为了确保冲突单元在另一个单元启动之前停止,必须声明 After= 或 Before= 依赖项。使用两个排序依赖项中的哪一个并不重要,因为停止作业始终在启动作业之前排序,请参阅下面 Before=/After= 中的讨论。
如果与单元 B 冲突的单元 A 计划与单元 B 同时启动,则事务要么失败(如果两者都是事务的必需部分),要么被修改以进行修复(如果一个或两个作业都不是事务的必需部分)。在后一种情况下,不需要的作业将被删除,或者如果两者都不是必需的,则将启动冲突的单元并停止冲突的单元。
因此,如果您想杀死B
并且C
无论何时开始A
,只需将其添加[Unit]
到A.service
[Unit]
Conflicts=B.service C.service
如果您将所有三个单元Conflict=
相互组合,那么您将选择要运行的一个。因此,启动 A 将杀死 B&C,启动 B 将杀死 A&C,启动 C 将杀死 A&B。
听起来你想B.service
默认运行,所以只有一个应该有WantedBy=multi-user.target
关系。不要将其添加到其他项(或不启用它们),否则它们都会尝试在启动时启动,并且它们要么全部失败,要么随机一个将继续运行。
听起来您也想B.service
在停止A.service
或时开始C.service
。尝试更多地考虑你想要什么,而不是你不想要什么。 Systemd 不存在在一个单元关闭时启动另一个单元的关系。要关闭整个系统,systemd 会引发shutdown.target
它与一切发生冲突,使它们崩溃。想象一下,如果C停止关机,在关机过程中启动B。