systemd中OnFailure=与Restart=的异常行为技术问询
解决systemd 231中
OnFailure=与Restart=行为不符的问题 我帮你梳理下嵌入式场景下systemd配置的核心逻辑——你遇到的问题本质是Restart=和OnFailure=的触发条件优先级没理清,导致硬件故障的主动退出和崩溃的意外退出被混淆处理了。先明确你的核心需求:
- 硬件故障时,foo_app主动返回码1 → 触发系统重启,不重启服务
- foo_app意外崩溃(段错误、异常终止等)→ systemd自动重启服务
关键配置原理(针对systemd 231)
systemd的Restart=默认是on-failure,会把所有非0退出码都当成“故障”触发重启,这就和你要的“主动返回1时不重启”冲突了。我们需要精准区分主动故障退出和意外崩溃两种场景:
- 用
RestartPreventExitStatus排除主动故障的退出码,让systemd遇到这个码时不重启服务 - 用
Restart=on-abnormal限定仅在意外崩溃时重启服务 - 用
OnFailure=绑定重启目标,确保服务因主动故障退出进入failed状态时触发系统重启
最终配置示例
foo.service 文件(路径一般是/etc/systemd/system/foo.service)
[Unit] Description=Hardware Monitor Service After=syslog.target # 服务进入failed状态时,触发系统重启 OnFailure=reboot.target [Service] Type=simple # 替换为你的foo_app实际路径 ExecStart=/usr/bin/foo_app # 仅在意外崩溃时重启:比如信号终止、超时、非预期退出码 Restart=on-abnormal # 明确指定:当foo_app主动返回码1时,禁止systemd重启服务 RestartPreventExitStatus=1 # 重启间隔(嵌入式场景可根据需求调整) RestartSec=3s # 可选:防止服务启动/停止超时hang住 TimeoutStartSec=10s TimeoutStopSec=5s [Install] WantedBy=multi-user.target
配置细节解释
Restart=on-abnormal:这个重启策略只会在服务意外终止时触发,包括:- 收到未捕获的崩溃信号(如SIGSEGV、SIGABRT)
- 服务启动/停止超时
- 退出码不在预期范围内的非主动终止
RestartPreventExitStatus=1:告诉systemd,即使退出码1属于“failure”(未被标记为成功退出),也不要重启服务,让服务直接进入failed状态,触发OnFailure逻辑OnFailure=reboot.target:当服务进入failed状态时,systemd会启动reboot.target,直接触发系统重启
测试与验证
- 重载systemd配置:
systemctl daemon-reload - 启动服务并设置开机自启:
systemctl enable --now foo.service - 模拟意外崩溃:用
kill -SIGSEGV $(pidof foo_app),查看systemctl status foo.service确认服务被重启 - 模拟硬件故障:让foo_app主动返回1,查看服务状态是否变为failed,同时系统开始重启
注意事项(针对systemd 231)
RestartPreventExitStatus在systemd 231中已经支持指定具体退出码,无需担心版本兼容性- 确保foo_app是前台运行(如果是后台fork模式,需将
Type改为forking) - 用
systemctl status foo.service查看退出状态,确认主动故障时显示exit-code=1,崩溃时显示signal=SEGV等信号信息
内容的提问来源于stack exchange,提问作者Matt K




