systemd ConditionPathExists 写两个路径,条件却不满足
ConditionPathExists一条只检查一个路径。按两个都存在或任选其一分别配置,核对drop-in残留及空赋值清除全部条件的范围。
两个文件都存在,服务却因路径条件没有满足而跳过启动。如果 unit 写成 ConditionPathExists=/etc/example/a.conf /etc/example/b.conf,要先改这条条件的表达方式:它接收一个绝对路径,不把空格两边拆成两个待检查文件。
这与服务程序启动后找不到配置不同。条件在开始执行启动任务时检查,未满足会跳过启动;不能因为服务没有处于 failed 就认定程序已经启动成功。下面按 systemd 262 的正式条件规则说明,实际配置仍需核对本机支持的指令。
两个文件都需要存在时写两条
在原配置中替换错误的那一条:
[Unit]
ConditionPathExists=/etc/example/a.conf
ConditionPathExists=/etc/example/b.conf
两条普通条件按 AND 判断,两个路径都存在才满足这部分条件。目录和其他文件系统对象也能满足“存在”,它不保证目标是普通文件、内容合法或服务用户能读取。若契约要求其他对象类型,应选相应的条件或让程序正确校验。
给原值加引号不会把它变成路径列表。路径本来就含空格时,与意图检查两个独立路径是两种需求,应按实际单个路径和本机 unit 解析规则处理。ConditionPathExistsGlob 检查的是通配匹配是否至少有对象,也不能当作一组必备文件全部存在。
任选一个文件时使用触发条件
若真正要求是两份配置任选其一存在,用触发条件表达:
[Unit]
ConditionPathExists=|/etc/example/a.conf
ConditionPathExists=|/etc/example/b.conf
这里的 | 属于 systemd 条件语法,不是 shell 管道。至少一条触发条件要满足,同时所有普通条件仍必须满足。例如 unit 原有另一个硬性检查,它不会因为上面任一文件存在就被忽略。
若使用否定条件,先写 | 再写 !。不要凭字符串外观改动逻辑:需要的究竟是任一文件存在、任一文件不存在,还是两个文件都存在,要与服务启动契约一致。
覆盖文件不能随意清除其他条件
先查看当前主 unit、drop-in 和已加载状态。以下名称是系统服务占位值,用户服务应在所属用户范围使用对应的 --user:
systemctl cat example.service
systemctl show example.service -p FragmentPath -p DropInPaths -p Conditions
journalctl -u example.service -b -n 60 --no-pager
只在 drop-in 末尾追加正确条件,可能仍留下原来的错误条件。优先修正本次可管理的错误定义;必须覆盖时注意,空的 ConditionPathExists= 会清空此前的全部条件列表,不只是此前同名条件。先列清所有仍需保留的条件,再按原顺序和逻辑完整重建,不能删除其他启动保护来让条件变绿。
路径检查会跟随符号链接,断开的链接不算目标存在。还要确认所检查的是管理器判断时的实际路径,以及其他准备 unit 的排序是否符合预期。条件不是等待文件产生的循环,也不保证文件随后一直存在;程序打开配置时仍需处理权限、删除竞争和内容错误。
重载后验证跳过与真正启动
保存原 unit 和覆盖文件,在本机验证语法及条件配置,再按原管理流程执行 daemon-reload。重新加载定义不会自动重启正在运行的服务。
在受控环境核对两个文件都在、仅其中一个在及两个都不在的结果,确认与 AND 或触发条件的选择一致。需要正式重启时安排原有维护窗口,启动后再检查程序实际读取的配置与业务状态,不能只看条件通过。
回退只恢复本次修改的条件和覆盖文件,保留其他 drop-in。重新加载后再次核对原启动契约;不要为了测试在业务运行中删除实际配置文件。


