trap 命令详解
在 Shell 脚本编程中,trap 是一个非常关键的命令,它用于捕获信号(Signals)并执行预定义的命令。
简单来说,它的作用是:当脚本被意外中断、报错或正常退出时,执行一些“善后工作”(比如清理临时文件、释放锁、打印日志)。
1. 为什么需要 trap?
假设你的 Go 程序在运行过程中产生了一些临时文件(如 /tmp/go-build-xyz),或者你的脚本启动了一个后台进程。如果用户突然按下 Ctrl + C,或者脚本报错崩溃,这些临时文件就会留在硬盘里,后台进程也会变成“僵尸”。
使用 trap 可以确保:无论脚本如何结束,清理逻辑都会执行。
2. 基本语法
Bash
trap "要执行的命令" 信号名称
-
信号名称:
-
EXIT:脚本无论以何种方式退出(正常或意外)都会触发。 -
SIGINT:用户按下Ctrl + C时触发。 -
SIGTERM:系统请求终止进程时触发。 -
ERR:当某条命令执行失败(返回非 0 值)时触发。
-
3. 常见使用场景
A. 自动清理临时文件(最推荐)
这是编写健壮脚本的标配:
Bash
#!/bin/bash
# 创建一个临时文件
tmp_file=$(mktemp)
echo "正在处理数据..."
# 只要脚本退出,就执行 rm -f
trap "rm -f $tmp_file; echo '清理完成'" EXIT
# 这里模拟复杂的逻辑
sleep 10
B. 捕获 Ctrl + C 并优雅退出
如果你不想让用户随随便便中断脚本,或者想在中断前保存进度:
Bash
#!/bin/bash
trap "echo '别急,正在保存进度...'; exit" SIGINT
while true; do
echo "后台运行中..."
sleep 2
done
C. 报错时自动报警
如果脚本执行中途出错,立即通知你:
Bash
#!/bin/bash
trap "echo '警告:脚本在第 $LINENO 行执行失败!'" ERR
ls /non_existent_folder # 这行会报错并触发 trap
4. 特殊用法:忽略信号
如果你正在执行一段极其重要、绝对不能被打断的代码(比如正在写入数据库或升级系统),可以暂时屏蔽信号:
Bash
trap "" SIGINT SIGTERM # 捕获这些信号但不执行任何动作(即忽略)
# 重要操作开始
echo "正在写入关键数据,请勿中断..."
sleep 5
# 重要操作结束
trap - SIGINT SIGTERM # 恢复信号的默认行为
5. 查看当前的 trap
你可以直接在终端输入 trap 来查看当前 Shell 环境中设置了哪些捕获。
6. 结合你目前服务器的实战
既然你在搞 Go 订阅系统,你可能会写一个 自动化编译并部署 的脚本:
Bash
#!/bin/bash
# 定义清理函数
cleanup() {
echo "正在停止旧进程..."
pkill my-go-app || true
}
# 脚本一旦运行失败或退出,就执行清理
trap cleanup EXIT ERR
echo "开始拉取代码并编译..."
go build -o my-go-app main.go
echo "启动程序..."
./my-go-app &
wait
💡 小贴士
-
EXIT 是万能的:大多数情况下,你只需要捕获
EXIT信号,因为它涵盖了正常退出和被杀掉的情况。 -
顺序很重要:
trap必须写在可能报错的代码之前,否则信号还没捕获,脚本就崩了。
你现在是否有写一些 .sh 脚本来管理你的 Go 程序?我可以帮你优化一下,加入 trap 逻辑,让它更稳健。