这是发生在我自己服务器上的真实故障。它最可怕的地方不在于严重,而在于 —— 它持续了 37 天,没有触发任何一次告警,没有任何一个业务受影响,所有人都以为系统一切正常。
那天做例行巡检,顺手查了一下网关服务的状态:
$ systemctl show openclaw-gateway.service -p NRestarts --value
302553
三十万次重启。第一反应是「看错了」,又跑了一遍 —— 数字还在涨,每 16 秒 +1。
NRestarts 这个绝大多数人不看的字段,在疯狂跳字。
查 journal 日志,模式很清晰:
$ journalctl -u openclaw-gateway | tail
Scheduled restart job, restart counter is at 302551
gateway already running (pid 3627080); lock timeout after 5000ms
Main process exited, code=exited, status=78/CONFIG
Scheduled restart job, restart counter is at 302552
...
真正的根因是两个同名 systemd 单元打架:
/etc/systemd/system/openclaw-gateway.service (系统级)
ExecStart=... gateway run ← 没有 --port
Restart=always
RestartSec=5
❌ 缺少 RestartPreventExitStatus=78
/root/.config/systemd/user/openclaw-gateway.service (用户级)
ExecStart=... gateway run --port 18789
RestartPreventExitStatus=78 ✅ 有这一行
死循环是这样形成的:
78(配置错误)退出RestartPreventExitStatus=78,于是 systemd 把它当成「崩溃」Restart=always + RestartSec=5 → 5 秒后立刻重启而用户级单元因为有那一行配置,识别出「退出码 78 是配置问题,不是崩溃」,一次都没重启过 —— 真正的网关(pid 3627080)稳定运行了 34 天。
重启次数: 302,553 次(8/10 起 36 天)
单次 CPU 时间:~7.6-9 秒(进程启动 + 加载 + 竞争锁超时)
累计 CPU: ≈ 21 CPU-天
每日损失: ~13.8 CPU-小时
日志量: 每天 88,431 行
syslog 占比: 36%(102,630 / 287,337 行)
journal 体积: 2.3 GB
一台常年负载 1.3~1.7 的机器,真凶之一就在这。
方案 A(最小侵入,推荐):给系统级单元补上那一行,让它对配置冲突退出码免疫,同时保留崩溃自愈能力。
# 1. 先备份
cp /etc/systemd/system/openclaw-gateway.service \
~/openclaw-gateway.service.bak-$(date +%Y%m%d-%H%M)
# 2. 精准插入一行(不要整文件覆盖!)
sed -i '/^RestartSec=5/a RestartPreventExitStatus=78' \
/etc/systemd/system/openclaw-gateway.service
# 3. 重载配置
systemctl daemon-reload
# 4. 验证:数字不再增长
systemctl show openclaw-gateway.service -p NRestarts --value
# 隔几分钟再跑一次,数字应该冻结
方案 B(更干净):确认用户级单元在跑(且开启了 lingering),直接停用重复的系统级单元。
systemctl --user is-active openclaw-gateway # 先确认 true
systemctl disable --now openclaw-gateway.service
daemon-reload 再验证。别在生产上「一把梭」。
修复前:NRestarts 每 16 秒 +1
修复后:
02:12:53 最后一次退出码 78
02:15:31 NRestarts = 308086
02:16:12 NRestarts = 308086
02:18:01 NRestarts = 308086 ← 连续 6 分钟冻结
负载 1min:1.06 → 0.09
监控系统通常盯的是「服务是否存活」「端口是否可达」。而重启风暴里,服务一直是活的(真网关在跑)。你的告警永远不会响。
状态是「在线」,变化率是「每 16 秒重启一次」。前者正常,后者爆炸。巡检必须把 NRestarts、重启次数、日志增速这类「变化指标」纳入检查。
崩溃会响,报错会响,磁盘满会响。空转不会响。它悄悄烧你的 CPU、撑你的日志,直到某天你顺手动了一个字段。
# 找出所有重启次数异常的服务
for u in $(systemctl list-units --type=service --no-legend | awk '{print $1}'); do
n=$(systemctl show "$u" -p NRestarts --value 2>/dev/null)
[ -n "$n" ] && [ "$n" -gt 5 ] && echo "$u → $n 次重启"
done
# 看看今天日志里谁在刷屏
journalctl --since today | awk '{print $5}' | sort | uniq -c | sort -rn | head
如果你跑完发现有服务重启了成百上千次,欢迎回来告诉我 —— 你可能也抓到了一只空转的鬼。👻
← 返回文章列表