systemd 服务启动时依赖网络但网络没起来就启动失败怎么写正确依赖

14次阅读

应使用Wants=network-online.target与After=network-online.target组合,并启用对应wait-online服务(如systemd-networkd-wait-online.service);避免仅用After=network.target或Requires=network-online.target等错误写法。

systemd 服务启动时依赖网络但网络没起来就启动失败怎么写正确依赖

要让 systemd 服务在真正有网络连接后才启动,不能只依赖 network.targetnetwork-online.target 就完事——因为它们的语义和实际行为容易被误解。关键在于区分“网络接口已配置”和“网络可达”。

Wants=network-online.target + After=network-online.target

这是最常用也最推荐的基础写法,但必须配合网络管理器(如 systemd-networkd 或 NetworkManager)正确启用 systemd-networkd-wait-online.serviceNetworkManager-wait-online.service

  • Wants=network-online.target 表示“我需要这个目标被激活”,不强制阻塞,但配合 After 才生效
  • After=network-online.target 确保服务在该目标**完成激活后**才开始启动
  • 注意:network-online.target 本身不会自己就绪,它依赖底层的 wait-online 服务来判断网络是否真正可用(比如能 ping 通网关或 dns

确认 wait-online 服务已启用并工作

不同网络管理器启用方式不同,漏掉这步会导致 network-online.target 立即就绪(假成功):

  • systemd-networkd:运行 sudo systemctl enable systemd-networkd-wait-online.service
  • NetworkManager:运行 sudo systemctl enable NetworkManager-wait-online.service
  • 验证是否生效:systemctl is-active systemd-networkd-wait-online(或对应服务),应为 active;再查 systemctl show network-online.target | grep ActiveState,应为 active 且不是瞬间变 active

对强网络依赖服务,加超时和重试更稳妥

即使用了 network-online.target,某些服务(如需访问特定 API 或内部 DNS)仍可能因网络策略、防火墙或服务端延迟而失败。可在 service 文件中增强鲁棒性:

  • StartLimitIntervalSec=60StartLimitBurst=3 防止反复崩溃刷日志
  • Restart=on-failure + RestartSec=10 让服务自动重试
  • 若逻辑允许,服务自身检查网络连通性(例如启动脚本里 until ping -c1 example.com &>/dev/NULL; do sleep 2; done),比纯依赖 systemd 更可控

避免常见错误写法

这些写法看似合理,实则无效或危险:

  • 只写 After=network.target:它只表示“网络服务已启动”,但接口可能还没配 IP、DHCP 没完成,不保证能上网
  • Requires=network-online.target:过于严格,如果 wait-online 失败(比如没网线),你的服务会直接无法启动,而非等待或重试
  • 在 service 中用 ExecStartPre=/usr/bin/sleep 10:硬编码延时不可靠,快网慢网都一样等,既不精准也不优雅
text=ZqhQzanResources