文章目录
- 1.cleanup_zombies.sh脚本
- 2.terminate_zombie_parents.sh:
- 3.监控僵尸进程monitor_zombies.sh:
- 4. 执行权限
- 5.定时处理
- 6.使用go执行
1.cleanup_zombies.sh脚本
#!/bin/bash
echo "检测并尝试清理僵尸进程..."
zombies=$(ps -eo pid,ppid,stat,cmd | grep 'Z' | awk '$3 ~ /Z/ {print $1","$2}')
if [ -z "$zombies" ]; then
echo "没有检测到僵尸进程!"
exit 0
fi
echo "发现以下僵尸进程:"
echo "$zombies" | tr ',' '\t' | awk '{printf "僵尸PID: %s 父进程PID: %s\n", $1, $2}'
echo "$zombies" | while IFS=',' read -r zombie_pid parent_pid; do
echo "尝试处理父进程 $parent_pid..."
kill -SIGCHLD "$parent_pid" 2>/dev/null
if ps -p "$parent_pid" > /dev/null 2>&1; then
echo "父进程 $parent_pid 仍在运行,可能需要手动检查。"
else
echo "父进程 $parent_pid 不存在,僵尸进程 $zombie_pid 将被 init 清理。"
fi
done
echo "僵尸进程清理完成。"
2.terminate_zombie_parents.sh:
#!/bin/bash
echo "检测并尝试终止僵尸进程的父进程..."
zombies=$(ps -eo pid,ppid,stat,cmd | grep 'Z' | awk '$3 ~ /Z/ {print $1","$2}')
if [ -z "$zombies" ]; then
echo "没有检测到僵尸进程!"
exit 0
fi
echo "发现以下僵尸进程:"
echo "$zombies" | tr ',' '\t' | awk '{printf "僵尸PID: %s 父进程PID: %s\n", $1, $2}'
echo "$zombies" | while IFS=',' read -r zombie_pid parent_pid; do
echo "尝试终止父进程 $parent_pid..."
kill -9 "$parent_pid" 2>/dev/null
if [ $? -eq 0 ]; then
echo "父进程 $parent_pid 已终止,僵尸进程 $zombie_pid 将被系统清理。"
else
echo "无法终止父进程 $parent_pid,请手动检查。"
fi
done
echo "父进程终止完成,僵尸进程将被清理。"
3.监控僵尸进程monitor_zombies.sh:
#!/bin/bash
logfile="/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" ]; then
echo "[$(date)] 没有僵尸进程。" >> "$logfile"
exit 0
fi
echo "[$(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; do
echo "[$(date)] 尝试处理父进程 $parent_pid..." >> "$logfile"
kill -SIGCHLD "$parent_pid" 2>/dev/null
if ! ps -p "$parent_pid" > /dev/null 2>&1; then
echo "[$(date)] 父进程 $parent_pid 不存在,僵尸进程 $zombie_pid 将被系统清理。" >> "$logfile"
else
echo "[$(date)] 父进程 $parent_pid 仍在运行,请手动检查。" >> "$logfile"
fi
done
echo "[$(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 main
import (
"bufio"
"bytes"
"fmt"
"os"
"os/exec"
"strings"
)
type ZombieProcess struct {
PID string
PPID 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 []ZombieProcess
scanner := 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
}