You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

systemd中OnFailure=与Restart=的异常行为技术问询

解决systemd 231中OnFailure=Restart=行为不符的问题

我帮你梳理下嵌入式场景下systemd配置的核心逻辑——你遇到的问题本质是Restart=OnFailure=的触发条件优先级没理清,导致硬件故障的主动退出和崩溃的意外退出被混淆处理了。先明确你的核心需求:

  • 硬件故障时,foo_app主动返回码1 → 触发系统重启,不重启服务
  • foo_app意外崩溃(段错误、异常终止等)→ systemd自动重启服务

关键配置原理(针对systemd 231)

systemd的Restart=默认是on-failure,会把所有非0退出码都当成“故障”触发重启,这就和你要的“主动返回1时不重启”冲突了。我们需要精准区分主动故障退出意外崩溃两种场景:

  1. RestartPreventExitStatus排除主动故障的退出码,让systemd遇到这个码时不重启服务
  2. Restart=on-abnormal限定仅在意外崩溃时重启服务
  3. 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,直接触发系统重启

测试与验证

  1. 重载systemd配置:systemctl daemon-reload
  2. 启动服务并设置开机自启:systemctl enable --now foo.service
  3. 模拟意外崩溃:用kill -SIGSEGV $(pidof foo_app),查看systemctl status foo.service确认服务被重启
  4. 模拟硬件故障:让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

火山引擎 最新活动