关键是用systemd的restart=on-failure、restartsec和startlimitburst/startlimitintervalsec三组参数组合实现可控自愈:前者限定重启触发条件,中者设置重试延迟,后者限制60秒内最多重启3次,超限则标记start-limit-hit并停止自动恢复。
要让服务在连续三次启动失败后自动重启并防止雪崩,关键不是“等它失败三次再动作”,而是用 systemd 的内置限流+重启策略组合实现可控自愈。核心是配置 restart=on-failure、restartsec 和 startlimitburst/startlimitintervalsec 这三组参数,它们共同决定“什么时候重启”和“最多重几次”。
设置基础重启行为
在服务的 .service 文件(如 /etc/systemd/system/myapp.service)的 [Service] 段中添加:
- Restart=on-failure:只在进程非零退出、被信号终止(如 SIGSEGV)、超时或 OOM kill 时重启,跳过正常退出(exit 0),避免误触发
- RestartSec=5:每次失败后等待 5 秒再尝试,给日志落盘、资源释放留出缓冲,也降低高频崩溃对系统的冲击
限制单位时间内的重启次数
防止单点故障引发无限循环重启拖垮系统,必须加频率控制:
在 Windows 11 上"直接发声"的 TTS(从 WSL2/TUI 调用 powershell.exe + System.Speech)。适用于用户说"说出来/读出来/语音播报/用TTS",或反馈"没声音/tts 生成的 mp3 是空的/播不出来",以及需要中文语音但 OpenClaw 内置 tts 不可用时。
- StartLimitIntervalSec=60:以 60 秒为一个统计窗口
- StartLimitBurst=3:该窗口内最多允许重启 3 次
- 超出后,systemd 将停止尝试,并把服务状态标记为
start-limit-hit,此时systemctl status会明确提示,需人工介入
验证与调试配置是否生效
改完别直接上线,按顺序操作确认效果:
- 运行
sudo systemctl daemon-reload重载配置 - 执行
sudo systemctl restart myapp.service应用新策略 - 用
systemctl show myapp.service | grep -E "(Restart|StartLimit)"核对当前值是否已更新 - 模拟一次崩溃:
sudo systemctl kill --signal=SIGSEGV myapp.service,观察是否在 5 秒后拉起;重复三次,第四次应失败并停住 - 查日志确认:
journalctl -u myapp.service -n 30 -f,能看到 “Started → Starting → Started” 循环,以及最终的start request repeated too quickly
补充建议:让失败真正可定位
单纯重启不解决根本问题,要确保每次失败都能留下线索:
- 在 service 文件中加上
StandardOutput=journal和StandardError=journal,保证所有输出进 journal - 若服务支持健康检查,加
ExecStartPost=/usr/bin/curl -f http://127.0.0.1:8000/health || exit 1,让探活失败也触发 Restart 逻辑 - 避免使用
Restart=always,它会掩盖正常退出场景,干扰对真实异常的判断










