linux僵尸线程清理

devtools/2024/11/27 3:29:03/

文章目录

    • 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..."# 向父进程发送 SIGCHLD 信号,通知其处理僵尸kill -SIGCHLD "$parent_pid" 2>/dev/null# 检查父进程是否仍在运行if 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"
)// ZombieProcess 结构体用于存储僵尸进程的 PID 和父进程的 PPID
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("僵尸进程清理完成。")
}// 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 []ZombieProcessscanner := 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], // 僵尸进程的 PIDPPID: 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
}

http://www.ppmy.cn/devtools/137291.html

相关文章

SpringBoot开发——Maven多模块工程最佳实践及详细示例

文章目录 一、前言二、Maven多模块工程的最佳实践1、项目结构清晰2、依赖管理统一3、插件配置统一4、版本控制一致5、模块间通信简化 三、详细示例1、项目结构2、父模块(parent)的pom.xml文件3、子模块(module-api)的pom.xml文件4…

html渲染优先级

HTML元素的渲染优先级通常由以下因素决定&#xff1a; 1.显示方式&#xff1a;块级元素比如 <div> 会自动开始一个新行&#xff0c;而内联元素比如 <span> 则不会。 可编辑性&#xff1a;某些元素默认是不可编辑的&#xff0c;而其他元素可能是可编辑的&#xff…

Redis Key 命名规范文档

开发过程中为确保 Redis 键名的一致性、可读性和易维护性&#xff0c;本规范旨在指导开发团队在使用 Redis 时设计合理的键名格式。 1. 命名格式 采用 模块:子模块:业务描述:标识 的分层格式&#xff0c;明确数据来源和用途。 层次清晰&#xff1a;从全局到具体逐步细化。唯一…

【Vue3 for beginner】普通插槽、具名插槽、作用域插槽

&#x1f308;Don’t worry , just coding! 内耗与overthinking只会削弱你的精力&#xff0c;虚度你的光阴&#xff0c;每天迈出一小步&#xff0c;回头时发现已经走了很远。 &#x1f4d7;插槽 在 Vue 3 中&#xff0c;插槽&#xff08;Slots&#xff09;是一个强大的功能&am…

【软考速通笔记】系统架构设计师③——信息安全技术基础知识

文章目录 一、前言二、信息安全基础知识2.1 信息安全的基本要求2.2 信息安全的范围2.3 网络安全表现2.4 安全措施包括 三、信息安全系统的组成框架3.1 技术体系&#xff1a;3.2 组织机构体系&#xff1a;3.3 管理体系 四、信息加解密技术4.1 对称密钥加密算法4.2 非对称密钥加密…

【强化学习的数学原理】第02课-贝尔曼公式-笔记

学习资料&#xff1a;bilibili 西湖大学赵世钰老师的【强化学习的数学原理】课程。链接&#xff1a;强化学习的数学原理 西湖大学 赵世钰 文章目录 一、为什么return重要&#xff1f;如何计算return&#xff1f;二、state value的定义三、Bellman公式的详细推导四、公式向量形式…

node.js fluent-ffmpeg 桌面推流

1&#xff0c;安装fluent-ffmpeg&#xff0c;npm install fluent-ffmpeg 2&#xff0c;推流代码&#xff1a; //stream.js const ffmpeg require(fluent-ffmpeg); const rtmpUrl "rtmp://localhost:1935/live/desktop"; //ffmpeg -f gdigrab -i desktop -vcode…

Axure PR 9 二级滑动选择器 设计交互

​大家好&#xff0c;我是大明同学。 这期内容&#xff0c;我们来探讨Axure中二级滑动选择器设计与交互技巧。 二级滑动选择器 创建滑动选择器所需的元件 1.在元件库中拖出两个中继器元件。 2.选中中继器元件&#xff0c;样式窗格中分别命名&#xff0c;“左边&#xff0c;…