4.2.6 常见信号应用场景:优雅退出、重载配置、超时控制
常见信号应用场景主要集中在进程生命周期管理与可运维性保障,典型目标是“优雅退出”“重载配置”“超时控制”。本节给出原理草图、可执行示例、排错要点与练习。
原理草图(信号在进程与子任务中的流转):
优雅退出(SIGTERM/SIGINT + 超时强杀)
- 目的:在终止前完成连接排空、状态落盘与资源释放。
- 关键命令解释:
- kill -TERM <pid>:发送SIGTERM请求进程优雅退出。
- kill -KILL <pid>:无法捕获,强制终止(最后手段)。
- ps -o pid,ppid,stat,cmd -p <pid>:查看进程状态。
示例:用脚本模拟优雅退出
# /opt/app/graceful.sh
#!/usr/bin/env bash
set -e
cleanup() {
echo "[`date +%T`] 收到SIGTERM,开始清理..."
# 模拟关闭连接与落盘
sleep 2
echo "[`date +%T`] 清理完成,退出"
exit 0
}
trap cleanup SIGTERM SIGINT
echo "[`date +%T`] 服务启动,PID=$$"
# 模拟主循环
while true; do
echo "[`date +%T`] 处理请求..."
sleep 1
done
运行与验证:
chmod +x /opt/app/graceful.sh
nohup /opt/app/graceful.sh >/tmp/graceful.log 2>&1 &
echo "PID=$(pgrep -f /opt/app/graceful.sh)"
kill -TERM $(pgrep -f /opt/app/graceful.sh)
tail -n 5 /tmp/graceful.log
预期效果:日志中出现“收到SIGTERM…清理完成,退出”。
排错要点:
- 进程不退出:确认是否捕获SIGTERM(strace -p <pid> -e signal)。
- 退出太慢:检查清理逻辑耗时,结合systemd的TimeoutStopSec。
重载配置(SIGHUP/SIGUSR1)
- 目的:不停机更新配置或切换日志。
- 关键命令解释:
- kill -HUP <pid>:请求进程重载配置。
- nginx -t:测试Nginx配置语法。
示例:以Nginx为例热加载
# 安装(如未安装)
# RHEL/CentOS:
# yum -y install nginx
# Debian/Ubuntu:
# apt-get -y install nginx
# 修改配置并校验
nginx -t
# 发送重载信号
kill -HUP $(cat /run/nginx.pid)
# 验证
ss -lntp | grep nginx
tail -n 20 /var/log/nginx/error.log
预期效果:端口持续监听,无进程重启;日志显示“signal process started”。
排错要点:
- 重载失败:先nginx -t,再确认pid文件路径。
- 配置未生效:检查是否有多份配置被include。
超时控制(SIGALRM 或外部watchdog)
- 目的:避免任务卡死、调用外部依赖超时。
- 关键命令解释:
- timeout 5s <cmd>:超时后发送SIGTERM(可用-k设定SIGKILL)。
- trap 'handler' ALRM:脚本内捕获定时器超时。
示例:使用timeout保护任务
# 模拟阻塞任务
sleep 100
# 通过timeout限制
timeout -k 2s 5s sleep 100
echo "返回码=$?" # 124表示超时
示例:脚本内超时控制
# /opt/app/timeout_job.sh
#!/usr/bin/env bash
set -e
trap 'echo "超时,退出"; exit 124' ALRM
(sleep 5; kill -ALRM $$) &
echo "开始任务..."
sleep 30
排错要点:
- 任务被误杀:提高超时阈值或区分“长任务”与“卡死”。
- 超时无响应:确认是否被trap捕获,或信号被屏蔽。
常用信号与默认行为速查(命令解释)
kill -l # 列出信号
kill -TERM <pid> # 优雅退出
kill -HUP <pid> # 传统重载/日志切换
kill -USR1 <pid> # 由应用自定义
kill -KILL <pid> # 强制终止
练习
1) 编写脚本捕获SIGTERM,模拟“停止接收新请求”后退出。
2) 修改Nginx配置,将worker_connections调小,重载并验证新值生效。
3) 使用timeout -k为一个备份脚本设定总超时与强杀时间。