shell函数结合trap命令的核心是用trap在脚本收到exit、int、term等信号时自动触发预定义的清理函数,需先定义cleanup函数再设置trap cleanup exit,确保资源释放可靠执行。

Shell函数结合trap命令,核心是用trap在脚本收到特定信号(如EXIT、INT、TERM)时自动触发预定义的清理函数。关键在于:清理函数必须提前定义,trap指令需在函数定义之后、可能出错的操作之前设置,且优先捕获EXIT信号以覆盖正常/异常退出场景。
定义清晰的清理函数
清理函数应只做释放资源的事,比如删除临时文件、恢复环境变量、关闭后台进程等。避免在其中调用可能失败或依赖外部状态的复杂逻辑。
- 函数名建议语义明确,如
cleanup或on_exit - 使用
rm -f、kill -TERM $pid 2>/dev/null等带容错的命令 - 可加日志输出便于调试:
echo "[INFO] Running cleanup..." >&2
用trap绑定EXIT信号(最常用且可靠)
EXIT信号会在脚本任何退出路径(包括exit、执行完最后一行、被set -e中断)时触发,无需额外判断退出原因,是最稳妥的选择。
- 写法:
trap cleanup EXIT(注意不加括号,不加;) - 必须在
cleanup函数定义后立即设置,否则会报“command not found” - 若脚本中有多处
exit,trap仍能保证清理函数执行一次
补充捕获常见中断信号(可选但推荐)
仅靠EXIT能覆盖大部分情况,但用户按Ctrl+C(INT)或kill(TERM)时,EXIT也生效;显式加上这些信号能让意图更明确,且某些极简环境可能对EXIT支持不一致。
- 写法:
trap cleanup INT TERM EXIT - 顺序无关,多个信号用空格分隔
- 避免捕获
KILL(9号信号)——它无法被trap,强行写上无意义
避免常见陷阱
实际使用中几个易错点直接影响清理是否生效:
-
不要在子shell里设置trap:如
(trap cleanup EXIT; some_cmd)中的trap只在子shell生效,主脚本退出时不触发 -
不要覆盖已有trap:重复
trap cmd SIGNAL会替换前一个,如需追加逻辑,应统一在一个trap里处理 -
清理函数内慎用exit:除非有意终止后续流程,否则
exit会导致trap链中断,建议用return或直接结束函数 -
临时文件路径要绝对且唯一:用
mktemp生成,避免多实例冲突,清理时用rm -f "$tmpfile"而非rm "$tmpfile"











