systemd 重启五次就不动了:start limit 把服务彻底停掉的三个细节

举报
yd_276135645 发表于 2026/11/02 06:06:01 2026/11/02
【摘要】 服务崩溃后 systemd 重启五次就彻底安静、status 显示 failed、手动 start 也不起来,通常是默认的 10 秒 5 次 start limit 被打满。本文用必死单元实测复现 Start request repeated too quickly,并说明 reset-failed 才能解锁、RestartSec 太小/太大会让限流失效或空转、StartLimitInterval

服务挂了,systemd 帮你重启了五次,然后彻底安静下来。systemctl status 显示 failed,日志停在最后一条 Failed with result 'exit-code',再往后什么都没有。你 systemctl restart 一下,它起来两秒又死,接着又是死的——但这次连重启都没有了。

这就是 StartLimitBurst / StartLimitIntervalSec 这对默认值在起作用。systemd 的默认策略是:10 秒内最多允许启动 5 次,超出后单元进入 failed 状态并且不再自动重启,日志里留下一条 Start request repeated too quickly。这条日志很容易被漏掉,因为它出现在 Scheduled restart job 之后,看起来像是重启链路自己坏了。

我在本机(systemd 255)用一个必死的单元复现了一下:

# systemd-run --unit=limit-test --property=Restart=always \
#   --property=RestartSec=0.2 /bin/false

4 秒后查状态:

Result=exit-code
NRestarts=5
ActiveState=failed

日志里第五次重启之后紧接着:

limit-test.service: Scheduled restart job, restart counter is at 5.
limit-test.service: Start request repeated too quickly.
limit-test.service: Failed with result 'exit-code'.

重启计数器停在 5,之后等了十几秒也没有第六条。自动恢复在这里就终止了,但你不会收到任何告警——单元就是 failed,安安静静。

细节一:卡在 start limit 之后,systemctl start 也会失败

这一点最坑。此时手动 systemctl start 的返回是:

Job for limit-test.service failed because the control process exited with error code.

或者干脆没有输出,退出码非 0,服务不启动、日志也不追加。原因是 rate limit 的门还关着,你被自己的限流挡住了。必须先清掉失败状态:

systemctl reset-failed myapp.service
systemctl start myapp.service

reset-failed 会清掉 restart counter 和 failed 标记。排障时如果只看到「重启没用」,先想到这一步,能省掉大量在代码里瞎找 bug 的时间。

细节二:RestartSec 太小才是常见元凶

限流窗口是「10 秒内 5 次」。如果进程是启动即退(配置错、端口被占、缺环境变量、依赖没起来),配上 RestartSec=1,五次启动两秒就用完了;配上 RestartSec=0.2,一秒内就打满。

反过来,如果 RestartSec=5,理论上一分钟能启动 12 次,但任意 10 秒窗口里最多 2 次——永远碰不到 5 次的阈值,限流形同虚设,服务会以每 5 秒一次的节奏无限重启,把日志和 CPU 慢慢拖干。

两种情况都不健康,正确的方向是退避而不是固定间隔:

[Unit]
StartLimitIntervalSec=300
StartLimitBurst=10

[Service]
Restart=on-failure
RestartSec=5

10 次 / 5 分钟意味着前 50 秒允许快速重试(扛过瞬时抖动),之后就必须真的死够久才会被判失败。再配一个 OnFailure= 单元去发通知,或者干脆用监控盯 systemctl show -p NRestarts:

systemctl show myapp.service -p NRestarts -p ActiveState

只要 NRestarts 在增长、ActiveState 还是 active,就是「在重启但没起来」的中间态,这时更该报警——比等它彻底 failed 有信息量得多。

细节三:StartLimitIntervalSec=0 不是「关掉限流」的优雅写法

StartLimitIntervalSec=0 确实关闭限流,让 systemd 无限重试。但它把「试探性重启」变成「每秒一次的死循环」:如果 RestartSec 也很小,进程会以毫秒级频率拉起、崩溃、拉起,journal 几秒钟就能写出几万行,磁盘和 CPU 都被吃满——本来只是想让它别放弃,结果把整机拖下水。真要关限流,RestartSec 必须同步调大。

附带一个配置位置的坑

这两个键历史上在 [Service] 段,从 systemd 230 起挪到了 [Unit]。写错位置的行为是静默失效,实测 systemd-analyze verify 会告诉你:

demo.service:9: Unknown key name 'StartLimitIntervalSec' in section 'Service', ignoring.

ignoring 三个字意味着你精心设计的 10 次 / 5 分钟根本不存在,实际跑的还是默认的 5 次 / 10 秒。改完配置务必跑一次 systemd-analyze verify,比看文档快。

检查清单

  • 服务隔一会儿就死、日志没有新内容 → 先看有没有 Start request repeated too quickly
  • 卡在 start limit 后手动也起不来 → systemctl reset-failed 再 start
  • 启动即退的服务 → RestartSec 别小于 5,限流窗口放大到分钟级
  • 只想让它一直重试 → StartLimitIntervalSec=0 必须配大 RestartSec
  • 别让自动恢复在无告警的 failed 状态里终止 → 监控 NRestarts 增长速度,或配 OnFailure=
  • 这两个键写在 [Unit],改完跑 systemd-analyze verify
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。