Ubuntu 僵尸进程自动清理的正确做法
一 核心原则
二 推荐的自动清理方案
#!/usr/bin/env bash
set -uo pipefail
while true; do
# 查找状态为 Z 或 z 的进程,仅输出 PID
mapfile -t zombies < <(ps -e -o pid,ppid,stat --no-headers | awk '$3 ~ /^[Zz]/ {print $1}')
if (( ${#zombies[@]} == 0 )); then
sleep 30
continue
fi
for zpid in "${zombies[@]}"; do
ppid=$(ps -o ppid= -p "$zpid" 2>/dev/null || true)
if [[ -n "$ppid" && "$ppid" -gt 1 ]]; then
# 优先尝试温和信号,不行再 SIGKILL 父进程
if ! kill -CHLD "$ppid" 2>/dev/null; then
kill -TERM "$ppid" 2>/dev/null || kill -KILL "$ppid" 2>/dev/null
fi
fi
done
sleep 30
done
sudo chmod +x /usr/local/bin/zombie-reaper.sh
sudo tee /etc/systemd/system/zombie-reaper.service >/dev/null <<'EOF'
[Unit]
Description=Zombie Process Reaper
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/zombie-reaper.sh
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now zombie-reaper.service
sudo crontab -e
# 每 2 分钟执行一次
*/2 * * * * /usr/local/bin/zombie-reaper.sh
上述做法属于“自动督促回收/结束父进程”的思路,能降低僵尸堆积,但根因修复仍需在应用或服务端完成。
三 从源头避免僵尸的产生
#include <signal.h>
#include <sys/wait.h>
void sigchld(int s){ while(waitpid(-1, NULL, WNOHANG) > 0); }
// 在 main 中注册:signal(SIGCHLD, sigchld) 或使用 sigaction
四 排错与注意事项