linux中进程异常退出时自动触发脚本的核心思路是通过外部监控机制(如systemd、supervisor、inittab或轮询脚本)捕获退出信号或状态变化,依据退出码执行响应脚本。

Linux 中进程异常退出时自动触发脚本,核心思路是「捕获退出信号或状态变化」,再由系统机制调用你的处理脚本。这不是靠进程自己“上报”,而是由外部监控者(如 systemd、supervisor、inittab 或自写脚本)感知到进程终止后,根据退出码或上下文决定是否执行你的脚本。
用 systemd 的 ExecStopPost 或 RestartPreventExitStatus
如果你的服务已托管在 systemd 下,这是最规范、最可靠的方式:
- ExecStopPost=:在服务主进程停止后(无论正常还是异常)无条件执行指定脚本,适合做清理、日志归档、告警通知等
-
RestartPreventExitStatus=:配合
Restart=on-failure使用,明确告诉 systemd 哪些退出码不算“异常”,避免误重启——而其他非列表中的退出码触发重启时,自然会走ExecStartPre或ExecStartPost,也可在此处嵌入你的响应逻辑 - 示例片段:
[Service]
ExecStart=/usr/local/bin/myapp
Restart=on-failure
RestartPreventExitStatus=0 15 # 退出码为0(成功)或15(SIGTERM)时不重启
ExecStopPost=/usr/local/bin/on-crash-notify.sh
用 Supervisor 的 eventlistener 或 program hooks
Supervisor 支持事件驱动模型,可监听进程状态变更:
- 启用
[eventlistener:crash_notifier]段,监听PROCESS_STATE_FATAL或PROCESS_STATE_STOPPED事件 - 配合
command=/usr/local/bin/on-supervisor-crash.sh,该脚本会收到标准输入的事件数据(含进程名、退出码、时间戳等) - 需确保 supervisor 配置中启用了
rpc_interface和supervisorctl权限,并重载配置:sudo supervisorctl reread && sudo supervisorctl update
用 inittab 的 respawn + 自定义 init 脚本
适用于传统 SysV init 系统(如旧版 CentOS/RHEL 6、Debian 7):
- 编辑
/etc/inittab,添加一行:
crsh:2345:respawn:/bin/sh -c 'exec /usr/local/bin/myapp 2>&1 | /usr/local/bin/crash-handler.sh' - 其中
respawn表示只要进程退出(无论原因),init 就立即拉起新实例;你可在crash-handler.sh中通过管道捕获 stderr/stdout,判断是否异常(比如含 "Segmentation fault" 或退出码非 0),再发邮件、写数据库或调用 webhook - 注意:修改后需运行
sudo telinit q重载 inittab
用轮询脚本 + exit code 判断(轻量级兜底方案)
若无法使用上述服务管理器,可用 Bash 脚本主动检查:
- 关键不是“进程是否存在”,而是“上次退出是否异常”——需记录并读取上一次运行的退出码
- 示例逻辑:
#!/bin/bash
LOG="/var/log/myapp/last_exit_code"
while true; do
pid=$(pgrep -f "myapp.py")
if [ -z "$pid" ]; then
exit_code=$(cat "$LOG" 2>/dev/null || echo "0")
if [ "$exit_code" != "0" ]; then
/usr/local/bin/on-abort.sh "$exit_code"
fi
nohup python /opt/myapp.py >>/var/log/myapp.log 2>&1 &
fi
sleep 10
done - 让被监控程序自身在退出前写入退出码(如
echo $? > /var/log/myapp/last_exit_code),或用wait -n捕获子进程退出码











