是否可以对多个单元中的任意一个指定 systemd 依赖性?
目前,我有一个单元 Z,它至少依赖于单元 A 或单元 B 中的一个。
将单元 A 配置为WantedBy
单元 Z,将单元 B 配置为WantedBy
单元 Z 基本可行。
但是,如果只有单元 A 或 B 中的一个能够启动,则启动过程将等待另一个单元超时,然后才能启动单元 Z。我想消除这个超时。
单元 A 和 B 需要超时才能正常运行,但是,一旦其中一个单元启动,就无需等待另一个单元超时即可启动单元 Z。
有没有办法指定单元 Z 依赖于单元 A 或单元 B,但在启动单元 Z 之前不需要等待单元 A 和单元 B 同时启动?
在 Debian 世界中,包装系统用于Provides
指定与我希望在这里完成的事情类似的内容。
我想要实现的目标
Debian 曾经支持keyscript
中的选项,crypttab
但上游重写了迁移到 的启动脚本后,Debian 并未重新实现该选项systemd
。以前,我使用 来keyscript
从 USB 驱动器读取密钥。目前,我使用systemd
单元文件来代替该keyscript
选项(单元 A)。效果非常好。但是,USB 驱动器很容易发生故障,因此为了实现冗余,我想在第二个 USB 驱动器上携带我的密钥的第二份副本。我想systemd
为第二个 USB 驱动器(单元 B)添加第二个单元文件,这样无论插入哪个 USB 驱动器,systemd
都可以使用该 USB 驱动器并继续操作而不会超时。
我尝试过的其他方法
使用Conflicts
指定 A 与 B 冲突,且 B 与 A 冲突。遗憾的是,systemd 在尝试启动单元 A 或 B 之前会处理冲突,并在尝试启动剩余单元之前从调度程序中删除其中一个单元。因此,Z 有时会失败,例如,如果 A 失败,但如果 B 已因与 A 冲突而被排除在考虑范围之外,则 B 会成功。
用来JobTimeoutSec
缩短超时时间。不幸的是,如果 A 和 B 超时,这可能会导致 Z 失败。
Michael Hampton 的建议。正如他所提到的,NTP 示例在每个客户端和目标之间创建了弱依赖关系。每个 NTP 客户端都需要目标,但目标不依赖于每个 NTP 客户端,因此这有效。但是,据我所知,弱依赖关系不会拉入单元,除非该单元还具有[Install]
指定其他依赖关系的部分。因此,当我拉入我的单元 A 和 B 时,WantedBy
该部分中的[Install]
会创建阻塞超时。如果我删除该[Install]
部分,单元 A 和 B 将被忽略。
答案1
这是 systemd 目标单元的一项工作。
我不会给出一个虚构的例子,而是给出一个已经存在于您的系统上的真实例子。
考虑 NTP。大多数计算机通过 NTP 同步,但有三个(甚至更多)NTP 客户端可供选择:systemd-timesyncd、chronyd 或(经典)ntpd。
这些 NTP 客户端的每个服务单元都是名为 的目标的一部分time-sync.target
,并且弱地需要它。
Before=time-sync.target
Wants=time-sync.target
因此,当您启动任何 NTP 客户端时,time-sync.target
将在 NTP 客户端启动后启动。请注意,它time-sync.target
本身是空的,实际上不会自行执行任何操作。
因此,如果您运行的服务需要系统时间已同步,否则将会失败,则您可以要求它仅在time-sync.target
启动后启动。
After=time-sync.target
Requires=time-sync.target
您应该能够轻松地将其适应于您自己的服务。
答案2
我认为如果此功能存在,它会出现在systemd.unit
手册页中,但我在那里没有看到它。
解决方案可以是使用一个小bash
脚本,只要 A 或 B 启动,该脚本就会成功,如果 A 和 B 都无法启动,则失败。