onfailure 是 systemd 单元级别的配置项,用于在服务进入 failed 状态时立即启动指定 unit(如自愈脚本 service),它不是轮询或外部监控,而是由 systemd 状态机驱动的毫秒级、一次性响应机制。

直接在 OnFailure= 里调用 Shell 脚本,是 systemd 原生支持的自愈机制,不需要额外轮询或守护进程。它只在服务真正失败时触发,精准、轻量、可审计。
OnFailure 是什么,不是什么
它是一个单元(unit)级别的配置项,写在 [Unit] 段里,指定“当本服务进入 failed 状态时,立即启动另一个 unit”。这个被启动的 unit 可以是另一个 service、一个 timer,或者——最常用——一个专为故障处理编写的 .service 文件,其 ExecStart= 就是你自己的 Shell 脚本。
它不是定时扫描,不轮询日志,也不依赖外部监控;它由 systemd 内部状态机驱动,毫秒级响应,且只触发一次(除非你手动或脚本再次触发失败)。
三步完成自愈链路
• 编写自愈脚本并赋予执行权限
脚本路径建议固定,比如 /usr/local/bin/on-failure-recover.sh。开头必须有 #!/bin/bash,建议加 set -e -u 防止意外继续执行。内容按需编写,例如:
- 清理临时文件或锁:
rm -f /tmp/myapp.lock - 重置设备节点:
modprobe -r mydriver && modprobe mydriver - 重启依赖服务:
systemctl try-restart dependency.service - 发送告警(可选):
logger -t "myapp-onfail" "Recovered after crash"
• 创建对应的 OnFailure service 文件
新建 /etc/systemd/system/myapp-onfail.service:
[Unit] Description=Recovery for myapp after failure After=network.target [Service] Type=oneshot ExecStart=/usr/local/bin/on-failure-recover.sh RemainAfterExit=yes StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target
注意:Type=oneshot 表示脚本执行完即退出,RemainAfterExit=yes 让 systemd 记录该服务为 “active (exited)”,便于排查是否已运行。
• 在主服务中声明 OnFailure
编辑你的主服务文件(如 /etc/systemd/system/myapp.service),在 [Unit] 段添加一行:
OnFailure=myapp-onfail.service
然后重载并启用:
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
systemctl daemon-reload<br>systemctl enable myapp.service
配合 Restart=on-failure 效果更稳
单独用 OnFailure 只管“出事了怎么办”,但不解决“出事了要不要再试一次”。所以推荐组合使用:
- 主服务中设
Restart=on-failure和RestartSec=3s:让进程先自动拉起一次 - 若这次拉起仍失败(比如因设备未就绪),systemd 进入 failed 状态,立刻触发
OnFailure= - 你的自愈脚本可以修复前置条件(如等待设备出现、改配置、清缓存),再由
Restart=自动重试主服务
这样形成“尝试 → 失败 → 自愈 → 再尝试”的闭环,比纯靠重启更可靠。
验证与排错要点
• 查看是否生效:systemctl show myapp.service | grep -E "(OnFailure|Restart)" 应显示对应值
• 模拟失败测试:systemctl kill --signal=SIGSEGV myapp.service(强制崩溃),然后观察 systemctl status myapp.service 和 journalctl -u myapp-onfail.service -n 20
• 常见坑:
– 脚本路径没写绝对路径(ExecStart= 必须绝对)
– 脚本没 +x 权限(chmod +x /usr/local/bin/on-failure-recover.sh)
– OnFailure= 后面的服务名拼错,或没 systemctl daemon-reload










