应使用 wants=network-online.target + after=network-online.target 并启用 systemd-networkd-wait-online.service 或 networkmanager-wait-online.service;依赖 nginx 需用 bindsto+after 并配合 type=notify 或端口轮询;串行启动须用 requires+after 且避免 defaultdependencies=no 破坏依赖链;排查卡住需检查逆向依赖、拼写错误及执行 daemon-reload。

systemd 服务启动依赖怎么写才不卡住 boot
多数人加 After=network.target 就以为网络就绪了,结果服务启动时 curl 还连不上外网——因为 network.target 只表示“网络服务已启动”,不保证 IP 分配完成或 DNS 可用。
真正要等网络就绪,得组合用:
-
Wants=network-online.target+After=network-online.target(推荐) - 确保
systemd-networkd-wait-online.service已启用(否则network-online.target永远不就绪) - 若用 NetworkManager,需启用
NetworkManager-wait-online.service
漏掉 wait-online 服务,network-online.target 会超时后直接进入 active 状态,看似成功,实则不可靠。
自定义服务想比 nginx 先启动,但总失败
直接写 After=nginx.service 不起作用——因为 nginx 默认是 Type=forking,systemd 只等主进程 fork 后就认为它“启动完成”,此时 worker 进程可能还没 bind 端口。
正确做法分两步:
- 在你的服务 unit 文件里加:
BindsTo=nginx.service+After=nginx.service(强制依赖顺序) - 同时让 nginx 显式通知就绪:在
[Service]段加Type=notify和ExecStartPost=/bin/systemctl notify --ready $MAINPID(需 nginx 编译时带 systemd 支持) - 或者更简单:改用
ExecStartPre=/usr/bin/sh -c 'while ! ss -tln | grep :80; do sleep 0.5; done'做端口轮询(适合临时调试)
硬写 After 而不确认目标服务真实就绪状态,等于没设依赖。
启科网络商城系统由启科网络技术开发团队完全自主开发,使用国内最流行高效的PHP程序语言,并用小巧的MySql作为数据库服务器,并且使用Smarty引擎来分离网站程序与前端设计代码,让建立的网站可以自由制作个性化的页面。 系统使用标签作为数据调用格式,网站前台开发人员只要简单学习系统标签功能和使用方法,将标签设置在制作的HTML模板中进行对网站数据、内容、信息等的调用,即可建设出美观、个性的网站。
多个服务要串行启动,但用了 Wants 却并行了
Wants= 是弱依赖,只影响启动时机,不阻塞;真正要串行,必须用 Requires= + After=,且目标服务不能设 DefaultDependencies=no。
常见翻车点:
- 自己写的 service 文件里写了
DefaultDependencies=no,却忘了手动补上Before=multi-user.target或其它基础 target,导致它被丢到启动末尾甚至不启动 - 两个服务互相
Wants,形成隐式循环,systemd 会静默忽略部分依赖 - 用
Conflicts=代替串行逻辑(比如 A 和 B 不能共存),结果误以为它能控制顺序
串行不是靠“希望它先”,而是靠 Requires 建立强依赖链,并确保整条链上每个单元都参与默认依赖图。
服务启动慢,但 systemctl status 看不出哪卡住
systemctl status myapp.service 显示 activating (start) 卡住,不代表代码慢——可能是 systemd 在等某个 target 就绪,而那个 target 因依赖缺失一直挂起。
排查三步法:
- 运行
systemctl list-dependencies --reverse --all myapp.service,看它等哪些东西 - 用
systemctl show myapp.service | grep -E "(After|Before|Wants|Requires)"检查显式依赖项是否拼写错误(比如写成nginx.serivce) - 开 debug 日志:
systemctl start myapp.service && journalctl -u myapp.service -o cat -f,重点看最后一行是不是 “Started …” 还是停在 “Starting …”
最常被忽略的是:自定义 service 文件放在 /etc/systemd/system/ 下,但忘记运行 systemctl daemon-reload,导致所有依赖配置全是旧的。









