绝大多数场景应使用 Wants 而非 Requires;Wants 是软依赖,目标失败不影响本服务启动,Requires 是硬依赖,目标失败将导致本服务进入 failed 状态,且两者均需配合 After/Before 才能控制启动顺序。

systemd 服务依赖用 Wants 还是 Requires?
Wants 和 Requires 都声明依赖,但行为完全不同:前者只“希望”目标服务启动,失败也不影响本服务;后者则强制要求目标服务必须成功启动,否则本服务直接失败并进入 failed 状态。实际写单元文件时,绝大多数场景该用 Wants ——比如 Web 服务想等网络就绪,用 Wants=network-online.target 更健壮;若误写成 Requires,只要 systemd-networkd-wait-online.service 超时(默认 90 秒),你的服务就起不来。
-
Requires触发硬依赖,会阻塞本服务的start流程 -
Wants是软依赖,目标服务启动失败或未定义,本服务照常运行 - 两者都不隐含启动顺序控制,需配合
After或Before使用
After 和 Before 不等于依赖,漏写 Wants/Requires 就白配
After=redis-server.service 只表示“我比 redis 启动晚”,但如果 redis 没被其他服务激活、也没设为开机启动,它根本不会启动——你的服务就会卡在“等待一个永远不会出现的时机”。常见错误是只写 After,结果服务启动时报 Job for xxx.service failed because a dependency job failed,日志里却看不到 redis 的任何启动记录。
- 必须成对使用:
Wants=redis-server.service+After=redis-server.service -
After不触发目标服务启动,仅排序;Wants才真正拉起依赖 - 若目标服务是 target(如
multi-user.target),Wants通常已由系统预设,此时只补After即可
如何查清某个服务实际依赖了哪些单元?
别信文档或猜测,用 systemctl list-dependencies --reverse xxx.service 看谁依赖它;用 systemctl list-dependencies --all xxx.service 看它自己依赖了哪些(含间接依赖)。注意默认只显示 active 单元,加 --all 才能看到所有声明的依赖,包括那些没启用、甚至不存在的单元。
-
list-dependencies输出的是解析后的依赖图,不是原始 unit 文件内容 - 如果某依赖显示为
not-found,说明 unit 文件写了Wants=xxx但系统里没有这个单元(拼错名、包未安装) - 依赖链过深时,加
--depth=3控制层数,避免刷屏
循环依赖检测不到?systemd 其实有静默截断机制
systemd 在加载 unit 文件阶段会检测显式循环(如 A Wants=B 且 B Wants=A),报错退出。但更常见的是隐式循环:A Wants=B + After=C,而 C 又通过 Requires 间接拉起 A。这种情况下 systemd 不报错,而是按加载顺序“截断”依赖链,导致部分 After 失效、启动顺序错乱。
- 日志中可能只出现
Found ordering cycle提示,不中断启动,但行为不可预测 - 推荐用
systemd-analyze verify xxx.service主动检查(需 systemd v245+) - 真实环境中,跨团队维护的服务最容易踩这类坑——A 团队加
After,B 团队加Wants,没人通盘看依赖图
真实依赖关系不是靠“觉得应该等”来写的,得从启动日志倒推、用 list-dependencies 验证、再用 verify 扫描潜在环。很多看似随机的启动失败,根源都在某一行漏掉的 Wants 或多写的 Requires。










