设计思路
- 捕获SIGTERM信号:使用
trap
命令捕获SIGTERM信号,当接收到该信号时,执行清理函数。
- 管理子进程:在创建子进程时,记录它们的进程ID(PID),以便后续关闭。可以将PID存储在数组中。
- 安全关闭子进程:向每个子进程发送SIGTERM信号,尝试正常关闭它们。
- 处理异常关闭:如果子进程在一定时间内没有响应SIGTERM信号,发送SIGKILL信号强制关闭。
- 清理临时文件:在关闭子进程后,删除脚本创建的所有临时文件。
- 输出关闭日志:记录每个子进程的关闭状态以及清理临时文件的结果,输出详细的关闭日志。
关键代码片段
#!/bin/bash
# 存储子进程PID的数组
child_pids=()
# 捕获SIGTERM信号
trap 'cleanup' SIGTERM
# 函数:创建子进程
create_child_process() {
some_command &
child_pids+=($!)
}
# 函数:清理资源并关闭子进程
cleanup() {
echo "Received SIGTERM, starting cleanup..."
local log_file="shutdown_log.txt"
exec > >(tee -a "$log_file") 2>&1
# 向子进程发送SIGTERM信号
for pid in "${child_pids[@]}"; do
echo "Sending SIGTERM to child process $pid"
kill -TERM "$pid"
done
# 等待子进程关闭,设置超时时间
local timeout=10
local remaining_pids=("${child_pids[@]}")
while (( ${#remaining_pids[@]} > 0 )); do
local pid="${remaining_pids[0]}"
if wait "$pid" 2>/dev/null; then
echo "Child process $pid has been successfully terminated"
else
if (( timeout <= 0 )); then
echo "Timeout reached, sending SIGKILL to child process $pid"
kill -KILL "$pid"
if wait "$pid" 2>/dev/null; then
echo "Child process $pid has been forcefully terminated"
else
echo "Failed to forcefully terminate child process $pid"
fi
else
echo "Child process $pid did not respond to SIGTERM, waiting..."
remaining_pids=("${remaining_pids[@]:1}")
sleep 1
((timeout--))
fi
fi
done
# 清理临时文件
if [ -e /tmp/temp_file ]; then
echo "Deleting temporary file /tmp/temp_file"
rm /tmp/temp_file
else
echo "Temporary file /tmp/temp_file does not exist"
fi
echo "Cleanup completed"
exit 0
}
# 主脚本逻辑,示例:创建一些子进程
create_child_process
create_child_process
# 主循环,使脚本持续运行
while true; do
sleep 1
done