SIGKILL无法捕获,因其是内核强制终止信号,设计上禁止捕获、忽略或阻塞,进程无任何响应机会。

Linux 中不能“捕获 ERR 信号处理脚本崩溃”,因为 ERR 不是系统信号,也不是进程崩溃的触发源。它只是 Bash 内置的一种特殊 trap 条件,仅在命令返回非零退出状态时触发,且与段错误(SIGSEGV)、非法指令(SIGILL)或被 OOM Killer 杀掉(SIGKILL)等真正的崩溃完全无关。
ERR 是什么,它能做什么
ERR 是 Bash 的伪信号,由 set -e 或显式 trap ... ERR 启用,作用是:当任意一条命令执行后返回非零状态(即失败),就立即执行你指定的处理逻辑。
- 它不响应内存越界、空指针解引用、除零等底层异常
- 它不拦截 SIGSEGV/SIGBUS/SIGFPE 等内核发送的崩溃信号
- 它只对 shell 层面的命令退出码起作用,比如
grep没匹配到内容、cp源文件不存在、mysql连接失败等
怎么正确设置 ERR 处理
要让 ERR trap 在函数内部也生效,必须开启 errtrace 选项:
set -eE # -e 启用自动退出,-E 让 ERR 陷阱继承进函数
error_handler() {
echo "命令失败:$BASH_COMMAND (行号 ${BASH_LINENO[0]})"
echo "上一个命令退出码:$?"
exit 1
}
trap error_handler ERR-
$BASH_COMMAND显示刚失败的命令文本 -
${BASH_LINENO[0]}给出错误发生的脚本行号(非绝对精确,但实用) - 避免在 trap 中直接调用可能出错的命令(如未检查存在的
rm -f),否则可能二次触发 ERR 导致死循环
真崩溃(如段错误)该怎么捕获
如果脚本里调用了 C 程序、二进制工具,或自己用 gcc 编译了有 bug 的代码,发生 SIGSEGV 时,Bash 的 trap ... ERR 完全无效。此时需:
- 用
systemctl status your-service和journalctl -u your-service -n 30查看是否出现Killed by signal SIGSEGV或SIGKILL - 确认是否 OOM:运行
dmesg -T | grep "killed process" - 对自研 C 程序,用
sigaction()注册SIGSEGV处理器,记录寄存器/栈帧并生成 coredump - 对 shell 调用的外部命令,用
timeout、ulimit -v限制资源,降低崩溃概率
推荐组合:兼顾错误和退出清理
真正健壮的脚本应同时处理逻辑错误与生命周期终结:
cleanup() { rm -f /tmp/mytemp.*; }
error_handler() { echo "ERR at line ${LINENO}: $BASH_COMMAND"; }
<p>trap cleanup EXIT # 任何方式退出都清理
trap error_handler ERR
set -eE-
EXITtrap 覆盖正常结束、exit、Ctrl+C(若没被其他 trap 拦截)、甚至ERR触发后的退出 -
ERR提供即时失败反馈,但不替代日志、监控或上游重试机制 - 不要指望靠 trap ERR “防止崩溃”,它只能帮你更快发现和响应 shell 命令级的失败


















