systemd服务启动顺序依赖需用After=与Wants=/Requires=组合:After=仅表时序,Wants=为弱依赖,Requires=为强依赖;避免循环依赖;验证须用systemd-analyze critical-chain等命令查真实链路,而非仅看配置。

systemd 服务启动顺序依赖怎么写
Linux 现在基本都用 systemd,控制启动顺序靠的是依赖关系,不是传统 SysV 的数字编号。写错依赖会导致服务起不来,或者起得太早——比如数据库还没监听,Web 服务就去连它,报 Connection refused。
关键不是“谁先谁后”,而是“谁等谁”。用 After= 和 Wants=(或 Requires=)组合才有效:
-
After=network.target只表示时间先后,不保证网络已就绪;真要等网卡配好,得加Wants=network-online.target+After=network-online.target -
Requires=redis.service表示强依赖:如果redis.service启动失败,本服务直接 abort,不会尝试启动 -
Wants=redis.service是弱依赖:redis.service启动失败不影响本服务继续,但本服务仍会在它之后启动(配合After=) - 避免循环依赖:
A Wants=B + After=B和B Wants=A + After=A会让systemd拒绝加载单元文件,报错Unit A has a dependency cycle with B
如何验证服务实际启动顺序
光看配置不顶用,得查真实执行流。最直接的方式是看启动时序图:
systemd-analyze plot > boot.svg
打开 boot.svg 就能看到所有服务横向排布、启动/结束时间轴。但更常用的是过滤关键服务:
-
systemd-analyze blame查耗时最长的服务(常暴露隐性阻塞) -
systemd-analyze critical-chain myapp.service显示从default.target到myapp.service的完整依赖链,每一步是否成功、耗时多少一目了然 -
journalctl -u myapp.service -u postgresql.service --since "1 hour ago"对比日志时间戳,确认 PostgreSQL 是否真在myapp.service启动前 ready
注意:systemd-analyze 默认只分析上次 boot,重启后数据刷新,别拿旧结果当依据。
自定义服务里误用 Type=forking 导致顺序错乱
很多老脚本习惯后台化(& 或 daemonize=yes),写 unit 文件时就随手设 Type=forking。但 systemd 对它的识别很脆弱:
- 必须严格指定
PIDFile=,且进程真要写这个文件;否则 systemd 认为服务“没起来”,后续依赖服务永远等不到它 - 如果程序 fork 多次(比如 supervisord 起多个子进程),
PIDFile里写的可能不是主进程 PID,systemd 会误判状态 - 推荐优先用
Type=simple(默认):只要主进程没 exit,就认为服务 running;适合现代 Go/Python 服务(不 daemonize,前台运行) - 实在要用
forking,务必加TimeoutSec=(比如TimeoutSec=60),防止 systemd 卡死等待一个永远不会出现的 PID 文件
容器或云环境里 network-online.target 不可靠
在 Docker、LXC、AWS EC2 等环境,network-online.target 经常假成功:网卡起来了,但 DHCP 还没回包、DNS 没通、甚至元数据服务(如 169.254.169.254)不可达。这时候硬等它,服务反而启动更慢甚至超时失败。
更稳妥的做法是让服务自己重试,而不是靠 systemd 等网络:
- 去掉
Wants=network-online.target,改用After=multi-user.target - 在服务启动命令里包装一层重试逻辑,比如:
ExecStart=/usr/bin/sh -c 'until nc -z localhost 5432; do sleep 2; done && /usr/local/bin/myapp' - 或者用
systemd原生的重启机制:Restart=on-failure+RestartSec=3,配合应用内连接池的重试,比外部等网络更健壮
真正难处理的不是“怎么配顺序”,而是“什么时候不该配顺序”——多数场景下,让服务自己应对依赖未就绪,比让 init 系统强行串行更可靠。










