👨⚕️ 主页: gis分享者
👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!
👨⚕️ 收录于专栏:Shell 面试

文章目录
- 一、🍀前言
-
- [1.1 ☘️示例](#1.1 ☘️示例)
- [1.2 ☘️使用语法](#1.2 ☘️使用语法)
- [1.3 ☘️知识扩展](#1.3 ☘️知识扩展)
一、🍀前言
在 Shell 脚本中,我们可以使用 trap 命令来捕捉和处理特定的信号。这对于管理中断、清理临时文件或确保脚本终止时有适当的处理非常有用。
1.1 ☘️示例
trap 命令的基本格式是:
powershell
trap 'commands' signals
其中:
- commands 是在捕捉到信号时要执行的命令。
- signals 是要捕捉的信号列表,多个信号可以用空格分隔。
一个常见的例子是捕捉 SIGINT 信号(通常是由 Ctrl-C 触发)来优雅地终止脚本:
powershell
#!/bin/bash
# 捕捉 SIGINT 信号并执行 cleanup 函数
trap 'cleanup' SIGINT
cleanup() {
echo "捕捉到 SIGINT 信号,正在清理临时文件..."
# 在这里添加清理临时文件或其他资源释放的代码
exit 0
}
echo "脚本正在运行,按 Ctrl-C 终止"
while true; do
sleep 1
done
1.2 ☘️使用语法
trap 命令基本语法
powershell
trap 'command' SIGNAL
常用信号类型
- SIGINT (2): 中断信号(Ctrl+C)
- SIGTERM (15): 终止信号
- SIGKILL (9): 强制终止信号(无法被捕获)
- SIGUSR1 (10): 用户自定义信号1
- SIGUSR2 (12): 用户自定义信号2
- SIGQUIT (3): 退出信号(Ctrl+\)
- SIGHUP (1): 挂起信号
- EXIT (0): 脚本退出
基本用法示例
1. 捕捉 Ctrl+C 信号
powershell
#!/bin/bash
# 捕捉 SIGINT 信号 (Ctrl+C)
trap 'echo "收到中断信号,正在退出..."; exit 1' SIGINT
echo "运行一个长时间任务..."
for i in {1..10}; do
echo "处理中... $i"
sleep 1
done
2. 捕捉脚本退出信号
powershell
#!/bin/bash
# 捕捉脚本正常退出
trap 'echo "脚本执行完毕,清理资源..."' EXIT
echo "开始执行任务..."
sleep 2
echo "任务完成"
# 脚本结束时会自动触发 EXIT 信号处理
3. 捕捉多种信号
powershell
#!/bin/bash
# 定义信号处理函数
cleanup() {
echo
echo "正在清理资源..."
# 在这里添加清理代码
rm -f /tmp/temp_file_$$
echo "清理完成,退出程序"
exit 0
}
# 捕捉多种信号
trap cleanup SIGINT SIGTERM SIGQUIT
# 创建临时文件
touch /tmp/temp_file_$$
echo "创建了临时文件 /tmp/temp_file_$$"
echo "运行中... 按 Ctrl+C 退出"
while true; do
sleep 1
done
4. 信号处理函数示例
powershell
#!/bin/bash
# 定义不同的信号处理函数
handle_sigint() {
echo
echo "捕获到 SIGINT 信号 (Ctrl+C)"
echo "你可以选择:"
echo "1) 继续执行"
echo "2) 退出程序"
read -p "请选择 (1/2): " choice
case $choice in
1) echo "继续执行...";;
2) exit 0;;
*) echo "无效选择";;
esac
}
handle_sigterm() {
echo
echo "捕获到 SIGTERM 信号"
echo "程序将在 3 秒后退出..."
sleep 3
exit 0
}
handle_exit() {
echo "脚本正常退出,执行清理工作"
# 清理临时文件等
}
# 设置信号处理器
trap handle_sigint SIGINT
trap handle_sigterm SIGTERM
trap handle_exit EXIT
# 主程序
echo "程序运行中,可以尝试发送信号"
echo "PID: $$"
for i in {1..100}; do
echo "循环次数: $i"
sleep 2
done
5. 高级用法:临时禁用和恢复信号处理
powershell
#!/bin/bash
# 定义信号处理函数
signal_handler() {
echo "信号处理函数被调用"
}
# 设置信号处理
trap signal_handler SIGINT
echo "信号处理已启用,PID: $$"
echo "现在可以按 Ctrl+C 测试"
sleep 5
# 临时禁用信号处理
trap '' SIGINT
echo "信号处理已禁用,Ctrl+C 将被忽略"
sleep 5
# 恢复信号处理
trap signal_handler SIGINT
echo "信号处理已恢复"
sleep 5
# 移除信号处理
trap - SIGINT
echo "信号处理已移除,使用默认行为"
sleep 5
6. 实用示例:带进度保存的长时间任务
powershell
#!/bin/bash
# 任务进度文件
PROGRESS_FILE="/tmp/task_progress_$$"
# 清理函数
cleanup() {
echo
echo "接收到终止信号,保存进度..."
echo "当前进度已保存到 $PROGRESS_FILE"
echo "下次运行时可以从中断处继续"
exit 0
}
# 设置信号处理器
trap cleanup SIGINT SIGTERM
# 初始化进度
if [ -f "$PROGRESS_FILE" ]; then
progress=$(cat "$PROGRESS_FILE")
echo "从进度 $progress 继续执行"
else
progress=0
fi
# 模拟长时间任务
echo "开始执行任务,按 Ctrl+C 可以安全中断"
for i in $(seq $progress 100); do
echo "进度: $i%"
echo $i > "$PROGRESS_FILE"
sleep 1
done
# 任务完成,清理进度文件
rm -f "$PROGRESS_FILE"
echo "任务完成"
trap 命令的其他用法
查看当前信号处理设置
powershell
# 显示所有已设置的信号处理
trap -p
# 显示特定信号的处理设置
trap -p SIGINT
移除信号处理
powershell
# 移除特定信号的处理
trap - SIGINT
# 移除所有信号处理
trap -
最佳实践
- 使用函数处理复杂逻辑 - 将信号处理逻辑封装在函数中
- 始终进行清理工作 - 在 EXIT 信号中清理临时文件和资源
- 避免在信号处理函数中执行复杂操作 - 保持信号处理函数简单快速
- 测试信号处理 - 确保信号处理按预期工作
- 考虑信号的时机 - 注意信号可能在关键操作时到达
通过合理使用 trap 命令,可以让 Shell 脚本更加健壮和用户友好,能够优雅地处理各种中断情况.
1.3 ☘️知识扩展
1. 常见信号
- SIGINT (2): 发送中断信号(Ctrl-C)。
- SIGTERM (15): 发送终止信号,默认的 kill 命令发送的信号。
- SIGKILL (9): 强制终止,不可被捕捉或忽略。
- SIGHUP (1): 发送挂起信号,通常在终端关闭时发送。
2. 使用 trap 清理临时文件: 我们可以在脚本运行时创建一些临时文件,而 trap 可以确保在脚本遇到中断时这些文件被及时清理:
powershell
#!/bin/bash
tmpfile=$(mktemp)
echo "临时文件:$tmpfile"
trap 'rm -f $tmpfile; exit' INT TERM EXIT
# 模拟一些处理
echo "处理数据..." > "$tmpfile"
sleep 10
echo "处理完成"
3. 组合使用多个信号: 我们可以同时捕捉多种信号,并在处理过程中根据具体信号做不同处理:
powershell
#!/bin/bash
trap 'echo "收到 SIGINT 信号"; exit 1' SIGINT
trap 'echo "收到 SIGTERM 信号"; exit 1' SIGTERM
echo "脚本开始运行..."
while true; do
sleep 1
done
4. 高级用法:
捕捉多个信号并执行同一个命令:
powershell
trap 'echo "捕获到信号"; cleanup' SIGINT SIGTERM
重置 trap 以处理默认行为:
powershell
trap - SIGINT SIGTERM