文章背景图

systemd 服务反复重启:退出码、启动限速与依赖故障排查

2026-08-09
0
-
- 分钟

服务不断“启动—退出—重启”,既可能造成业务抖动,也可能刷满日志、打爆下游或触发 systemd 启动限速。正确做法是先确认最后一次失败原因,再决定是否继续自动重启。

一、确认服务当前状态

systemctl status <service> --no-pager -l
systemctl show <service> -p ActiveState -p SubState -p Result -p ExecMainStatus -p NRestarts
systemctl is-failed <service>

记录 ActiveState、Result、主进程退出码和累计重启次数。activating (auto-restart) 表示正在等待下一次重启,start-limit-hit 表示单位启动过于频繁被 systemd 阻止。

二、读取完整日志

journalctl -u <service> --since '-30 min' --no-pager -o short-precise
journalctl -u <service> -b --no-pager
journalctl -u <service> -b -1 --no-pager

如果日志量很大,先按时间和错误关键字过滤。不要只看 systemctl status 最后十几行,它可能遗漏真正的首个错误。

三、检查退出码、信号和 core dump

systemctl show <service> -p ExecMainCode -p ExecMainStatus -p Result
coredumpctl list <service>
coredumpctl info <service>

常见结果包括 exit-code、signal、core-dump、timeout、watchdog、resources 和 start-limit。若存在 core dump,应先保存现场,再在隔离环境分析。

四、检查 unit 的真实配置

systemctl cat <service>
systemctl show <service> -p FragmentPath -p DropInPaths -p Environment
systemd-analyze verify /etc/systemd/system/<service>.service

重点检查:

  • ExecStart 路径、参数、用户和工作目录;

  • EnvironmentFile 是否存在、权限是否正确;

  • Restart=RestartSec=

  • StartLimitIntervalSec=StartLimitBurst=

  • 依赖、挂载点、网络和启动顺序;

  • TimeoutStartSecTimeoutStopSec 和 watchdog。

systemctl cat 会显示主文件和 drop-in,避免只修改一个被覆盖的配置文件。

五、手工验证启动条件

在不影响生产的前提下,以 unit 配置的用户验证文件和端口:

namei -l /path/to/binary
sudo -u <user> test -r /path/to/config && echo readable
ss -lntp
df -hT
free -h

如果应用支持配置检查或前台调试模式,先执行只读校验。不要直接复制 ExecStart 并以 root 运行,否则可能掩盖权限和环境问题。

六、检查依赖关系

systemctl list-dependencies <service>
systemctl list-dependencies --reverse <service>
systemd-analyze critical-chain <service>

数据库、网络挂载、证书、DNS 或下游端口未准备好时,应用可能立即退出。除了 systemd 的 After/Requires,还要检查应用自己的重试和健康检查逻辑。

七、应急处理步骤

  1. 如果重启正在冲击数据库或下游,先停止自动重启:systemctl stop <service>

  2. 保存 journal、unit 配置、环境和 core dump 信息。

  3. 修复配置、权限、端口冲突、依赖或资源问题。

  4. 执行应用配置检查,再启动一次观察。

  5. 确认根因已处理后,使用 systemctl reset-failed <service> 清除失败/限速状态。

  6. 启动服务并持续观察日志、端口、健康检查和业务指标。

不要反复执行 reset-failedstart 来绕过启动限速。限速是在防止错误服务形成无限重启风暴。

八、合理的重启策略

Restart=always 并不适合所有服务。配置错误、数据损坏和权限错误通常不会因为重启而恢复。应根据失败类型设置策略,并使用合理的 RestartSec 退避,避免毫秒级重启循环。

对于依赖外部服务的应用,还应在应用层实现指数退避、熔断和明确的启动失败日志。

九、长期治理

  • 监控 NRestarts、退出码、start-limit-hit 和服务可用性。

  • 发布前执行 unit 校验和应用配置检查。

  • unit 文件和 drop-in 纳入版本管理。

  • 为配置错误、端口冲突、依赖不可用和 OOM 建立演练。

  • 日志包含启动阶段、配置路径、依赖地址和明确退出原因。

systemd 只是执行重启策略。真正需要修复的是服务为什么退出,以及为什么同一个失败会被快速重复。

原创

systemd 服务反复重启:退出码、启动限速与依赖故障排查

本文链接: systemd 服务反复重启:退出码、启动限速与依赖故障排查

本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

评论交流

文章目录