4.2.5 信号发送与处理:kill、pkill、killall、trap
信号发送与处理:kill、pkill、killall、trap#
1. 原理概览(信号流转与处理)
- 信号是内核向进程发送的异步事件。
- 典型信号:SIGTERM(15)(请求退出)、SIGKILL(9)(强制终止)、SIGHUP(1)(重载/挂起)、SIGINT(2)(Ctrl+C)、SIGSTOP(19)(停止)、SIGCONT(18)(继续)。
- 优先使用可捕获的信号(如 SIGTERM),便于进程清理资源。
2. kill:按 PID 发送信号(精准控制)
- 语法:kill [-signal] PID
- 命令解释:
- -15 或不写信号:发送 SIGTERM
- -9:发送 SIGKILL
- -1:发送 SIGHUP
- -l:列出所有信号
# 1) 观察目标进程
ps -ef | grep nginx
# 2) 优雅退出(推荐)
kill -15 1234
# 3) 强制终止(仅用于无响应进程)
kill -9 1234
# 4) 触发重载(如服务支持 SIGHUP)
kill -1 1234
# 5) 查看信号列表
kill -l
3. pkill:按名称/条件匹配进程(批量控制)
- 语法:pkill [-signal] pattern
- 常用参数说明:
- -f:匹配完整命令行
- -u:限制用户
- -n:最新一个进程
# 终止所有 nginx 进程(默认 SIGTERM)
pkill nginx
# 匹配命令行关键字,终止应用
pkill -f "java.*app.jar"
# 仅杀 www 用户的 nginx
pkill -u www -f nginx
# 仅终止最新启动的一个进程
pkill -n -f "python app.py"
4. killall:按进程名批量发送信号(名称严格匹配)
- 语法:killall [-signal] process_name
- 更适合单一服务的统一操作,避免 -f 误匹配。
# 优雅重载 nginx
killall -HUP nginx
# 强制终止 mysqld
killall -9 mysqld
5. trap:Shell 中捕获信号(清理与回滚)
- 语法:trap 'commands' SIGNAL
- 常用场景:清理临时文件、释放锁、优雅退出。
#!/bin/bash
# 文件:/opt/scripts/backup.sh
LOCK=/tmp/backup.lock
touch "$LOCK"
cleanup() {
echo "清理资源..."
rm -f "$LOCK"
exit 0
}
# 捕获 SIGINT/SIGTERM,确保清理
trap 'cleanup' SIGINT SIGTERM
echo "开始备份..."
sleep 30
echo "备份完成"
cleanup
- 取消捕获并恢复默认:
trap - SIGINT
6. 排错与验证(常见问题定位)
- 进程不退出:
- 可能忽略/捕获 SIGTERM,使用 strace -p PID 看是否响应。
- 误杀进程:
- pkill -f 匹配过宽,先用 pgrep -af pattern 验证。
- 无法重载:
- 服务不支持 SIGHUP,查看官方文档或日志确认。
# 先确认将要匹配的进程
pgrep -af "java.*app.jar"
# 跟踪进程对信号的反应
strace -p 1234 -e trace=signal
7. 练习与实操(可复制执行)
1) 启动一个可控测试进程:
sleep 600 &
echo $! # 输出 PID
2) 发送不同信号并观察:
kill -15 <PID> # 优雅退出
kill -9 <PID> # 强制退出
3) 编写脚本测试 trap:
cat > /tmp/trap_test.sh <<'EOF'
#!/bin/bash
trap 'echo "收到 SIGINT,清理后退出"; exit 0' SIGINT
echo "运行中,按 Ctrl+C 触发..."
sleep 60
EOF
chmod +x /tmp/trap_test.sh
/tmp/trap_test.sh
4) 验证 pkill 的匹配范围:
pgrep -af "sleep 600"
pkill -f "sleep 600"