linux僵尸线程清理
·
文章目录
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..."
# 向父进程发送 SIGCHLD 信号,通知其处理僵尸
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"
)
// ZombieProcess 结构体用于存储僵尸进程的 PID 和父进程的 PPID
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("僵尸进程清理完成。")
}
// findZombies 使用 `ps` 命令查找僵尸进程
func findZombies() ([]ZombieProcess, error) {
// 执行 ps 命令,列出所有进程的 PID, PPID 和状态
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)
// 检查进程状态是否为 'Z'(僵尸进程)
if len(fields) >= 3 && strings.Contains(fields[2], "Z") {
zombies = append(zombies, ZombieProcess{
PID: fields[0], // 僵尸进程的 PID
PPID: fields[1], // 僵尸进程的父进程 ID
})
}
}
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("解析 ps 命令输出失败: %w", err)
}
return zombies, nil
}
// notifyParent 向父进程发送 SIGCHLD 信号,通知其处理僵尸进程
func notifyParent(ppid string) error {
// 使用 kill 命令发送 SIGCHLD 信号
cmd := exec.Command("kill", "-SIGCHLD", ppid)
err := cmd.Run()
if err != nil {
return fmt.Errorf("发送 SIGCHLD 失败: %w", err)
}
return nil
}
// isParentActive 检查父进程是否仍然活跃
func isParentActive(ppid string) bool {
// 使用 ps 命令检查父进程是否存在
cmd := exec.Command("ps", "-p", ppid)
err := cmd.Run()
return err == nil
}
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)