首页/系统/Linux 运维命令速查/trap shell 信号与清理钩子
进程与作业69 条

trap shell 信号与清理钩子

脚本的「收尾保障」:退出/中断时删临时文件、收尾子进程、记录失败行号;写可靠脚本的必修课。

Linux 运维命令速查系统更新于 2026-10-13

trap 是脚本的收尾保障

trap 用于注册信号与特殊事件的钩子:脚本退出(EXIT)时删除临时文件、收到 Ctrl+C(INT)或 TERM 时优雅退出、命令失败(ERR)时打印出错行号。写法是 trap '命令' 信号列表。要清楚 KILL 与 STOP 无法被捕获 —— 任何进程都拦不住,所以别用 trap 去拦截 kill -9。

基本信息

适用平台bash/sh/ksh(POSIX 支持 trap;ERR 与 DEBUG 是 bash 扩展)
语法trap '命令' 信号...;trap - 信号 恢复默认
常用事件EXIT 退出、INT/TERM 中断、HUP 挂断、ERR 命令失败
相关变量LINENO、BASH_COMMAND、$?
查看当前注册trap -p(bash)
不可捕获KILL 与 STOP

典型使用场景

  • 临时目录与临时文件的清理
  • 脚本被中断时优雅收尾(发送通知、释放锁)
  • 失败时打印出错行号与命令,便于定位
  • 批处理脚本的锁文件保障,避免残留死锁
  • 封装公共函数库时统一日志与错误处理

基础用法

基础用法
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT           # 正常结束或被中断都会清理

trap 'echo "[中断] 正在退出"; exit 130' INT TERM
trap 'echo "[ERR] line $LINENO: $BASH_COMMAND" >&2' ERR
set -euo pipefail                    # 与 ERR 陷阱配合使用
trap - EXIT                          # 需要时恢复默认行为
trap -p EXIT                         # 查看当前注册的命令(bash)

信号与用途

信号/事件触发时机典型用途
EXIT脚本退出,含被中断的情况清理临时文件、释放锁
INTCtrl+C打印提示并优雅退出
TERMkill 的默认信号收尾通知、保存中间状态
HUP终端挂断重载配置或退出
ERR命令返回非零(bash 扩展)打印行号与命令,定位失败点
KILL / STOP无法被捕获不能拦截,别写对应的 trap
trap 后面的命令用双引号会在注册时就把变量展开,希望触发时才取值就用单引号,例如 trap 'rm -rf "$tmp"' EXIT。
EXIT 陷阱里的清理命令如果失败,可能覆盖脚本原本的退出码:关键脚本要显式保存 $? 并在清理完成后按原退出码退出。
常见组合:set -euo pipefail 配合 ERR 陷阱记录行号,EXIT 陷阱只负责清理,两者分工清楚;把清理逻辑写进 ERR 会导致部分失败场景下不执行。
信号处理函数里避免耗时操作:长时间清理会让 Ctrl+C 看起来没反应,可以先打印一行提示再执行,必要时把重活拆到后台。
POSIX sh 对 ERR 与 LINENO 的支持不如 bash 完整:脚本要在 sh 下运行时,先确认执行环境,行号定位这类能力按 bash 设计。

易错点

  • 给 KILL/STOP 写 trap:这两个信号无法被捕获,写了也不生效,只会带来错误的安全感
  • trap 命令用双引号:变量在注册时被展开,触发时拿到的是旧值
  • 以为子 shell 的 trap 会继承:子 shell 内注册的 trap 只作用于该子 shell
  • EXIT 陷阱覆盖退出码:清理命令的返回值替换了原退出码,上游判断随之出错

数据来源与参考

  • man 1 bash(Bash 参考手册 trap 章节)

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌