文章目录
- 1.cleanup_zombies.sh脚本
- 2.terminate_zombie_parents.sh:
- 3.监控僵尸进程monitor_zombies.sh:
- 4. 执行权限
- 5.定时处理
- 6.使用go执行
1.cleanup_zombies.sh脚本
#!/bin/bashecho "检测并尝试清理僵尸进程..."
zombies=$(ps -eo pid,ppid,stat,cmd | grep 'Z' | awk '$3 ~ /Z/ {print $1","$2}')
if [ -z "$zombies" ]; thenecho "没有检测到僵尸进程!"exit 0
fiecho "发现以下僵尸进程:"
echo "$zombies" | tr ',' '\t' | awk '{printf "僵尸PID: %s 父进程PID: %s\n", $1, $2}'
echo "$zombies" | while IFS=',' read -r zombie_pid parent_pid; doecho "尝试处理父进程 $parent_pid..."kill -SIGCHLD "$parent_pid" 2>/dev/nullif ps -p "$parent_pid" > /dev/null 2>&1; thenecho "父进程 $parent_pid 仍在运行,可能需要手动检查。"elseecho "父进程 $parent_pid 不存在,僵尸进程 $zombie_pid 将被 init 清理。"fi
doneecho "僵尸进程清理完成。"
2.terminate_zombie_parents.sh:
#!/bin/bashecho "检测并尝试终止僵尸进程的父进程..."
zombies=$(ps -eo pid,ppid,stat,cmd | grep 'Z' | awk '$3 ~ /Z/ {print $1","$2}')
if [ -z "$zombies" ]; thenecho "没有检测到僵尸进程!"exit 0
fiecho "发现以下僵尸进程:"
echo "$zombies" | tr ',' '\t' | awk '{printf "僵尸PID: %s 父进程PID: %s\n", $1, $2}'
echo "$zombies" | while IFS=',' read -r zombie_pid parent_pid; doecho "尝试终止父进程 $parent_pid..."kill -9 "$parent_pid" 2>/dev/nullif [ $? -eq 0 ]; thenecho "父进程 $parent_pid 已终止,僵尸进程 $zombie_pid 将被系统清理。"elseecho "无法终止父进程 $parent_pid,请手动检查。"fi
doneecho "父进程终止完成,僵尸进程将被清理。"
3.监控僵尸进程monitor_zombies.sh:
#!/bin/bashlogfile="/var/log/zombie_cleanup.log"
echo "[$(date)] 开始检测僵尸进程..." >> "$logfile"
zombies=$(ps -eo pid,ppid,stat,cmd | grep 'Z' | awk '$3 ~ /Z/ {print $1","$2}')
if [ -z "$zombies" ]; thenecho "[$(date)] 没有僵尸进程。" >> "$logfile"exit 0
fiecho "[$(date)] 发现以下僵尸进程:" >> "$logfile"
echo "$zombies" | tr ',' '\t' | awk '{printf "僵尸PID: %s 父进程PID: %s\n", $1, $2}' >> "$logfile"
echo "$zombies" | while IFS=',' read -r zombie_pid parent_pid; doecho "[$(date)] 尝试处理父进程 $parent_pid..." >> "$logfile"kill -SIGCHLD "$parent_pid" 2>/dev/nullif ! ps -p "$parent_pid" > /dev/null 2>&1; thenecho "[$(date)] 父进程 $parent_pid 不存在,僵尸进程 $zombie_pid 将被系统清理。" >> "$logfile"elseecho "[$(date)] 父进程 $parent_pid 仍在运行,请手动检查。" >> "$logfile"fi
doneecho "[$(date)] 僵尸清理完成。" >> "$logfile"
4. 执行权限
chmod +x cleanup_zombies.sh
chmod +x terminate_zombie_parents.sh
chmod +x monitor_zombies.sh
5.定时处理
运行 :手动清理僵尸:./cleanup_zombies.sh 强制终止父进程;
bash 定期监控(结合 cron 使用): 将 monitor_zombies.sh 添加到 cron,每分钟运行一次:
crontab -e * * * * * /path/to/monitor_zombies.sh
6.使用go执行
package mainimport ("bufio""bytes""fmt""os""os/exec""strings"
)
type ZombieProcess struct {PID stringPPID string
}func main() {fmt.Println("检测并尝试清理僵尸进程...")zombies, err := findZombies()if err != nil {fmt.Printf("无法检测僵尸进程: %v\n", err)return}if len(zombies) == 0 {fmt.Println("没有检测到僵尸进程!")return}fmt.Println("发现以下僵尸进程:")for _, z := range zombies {fmt.Printf("僵尸PID: %s 父进程PID: %s\n", z.PID, z.PPID)}for _, z := range zombies {fmt.Printf("尝试通知父进程 %s 清理僵尸进程 %s...\n", z.PPID, z.PID)err := notifyParent(z.PPID) if err != nil {fmt.Printf("无法通知父进程 %s: %v\n", z.PPID, err)continue}if isParentActive(z.PPID) {fmt.Printf("父进程 %s 仍在运行,请手动检查。\n", z.PPID)} else {fmt.Printf("父进程 %s 不存在,僵尸进程 %s 将由系统清理。\n", z.PPID, z.PID)}}fmt.Println("僵尸进程清理完成。")
}
func findZombies() ([]ZombieProcess, error) {cmd := exec.Command("ps", "-eo", "pid,ppid,stat")output, err := cmd.Output()if err != nil {return nil, fmt.Errorf("执行 ps 命令失败: %w", err)}var zombies []ZombieProcessscanner := bufio.NewScanner(bytes.NewReader(output))for scanner.Scan() {line := scanner.Text()fields := strings.Fields(line)if len(fields) >= 3 && strings.Contains(fields[2], "Z") {zombies = append(zombies, ZombieProcess{PID: fields[0], PPID: fields[1], })}}if err := scanner.Err(); err != nil {return nil, fmt.Errorf("解析 ps 命令输出失败: %w", err)}return zombies, nil
}
func notifyParent(ppid string) error {cmd := exec.Command("kill", "-SIGCHLD", ppid)err := cmd.Run()if err != nil {return fmt.Errorf("发送 SIGCHLD 失败: %w", err)}return nil
}
func isParentActive(ppid string) bool {cmd := exec.Command("ps", "-p", ppid)err := cmd.Run()return err == nil
}