一、定位僵尸进程
ps命令:通过ps aux | grep '[Zz]'或ps -A -ostat,ppid,pid,cmd | grep -e '^[Zz]'命令,筛选出状态为“Z”(僵尸状态)的进程,输出结果中会显示僵尸进程的PID(进程ID)、PPID(父进程ID)、状态及命令信息。top命令:运行top后,按Shift + M(按内存使用排序)或Shift + P(按CPU使用排序),在进程列表中查找状态为“Z”的进程,直观查看僵尸进程的资源占用情况。htop命令(可选):若未安装,可通过sudo apt-get install htop安装,运行后僵尸进程会以红色“Z”状态显示,支持交互式操作(如按F9键直接杀死进程)。二、修复僵尸进程
kill命令清除,需先找到其父进程ID(PPID),再杀死父进程,使僵尸进程变为孤儿进程,由系统init进程(PID为1)自动回收。操作步骤:
ps -o ppid= <僵尸进程PID>命令获取父进程ID;kill -9 <父进程PID>终止父进程(-9为强制终止信号,需谨慎使用,避免影响关键服务)。SIGCHLD信号:kill -s SIGCHLD <父进程PID>命令向父进程发送信号,通知其回收子进程资源。部分父进程需提前配置信号处理函数(如sigaction)才能响应此信号。sudo systemctl restart nginx,重启MySQL的命令为sudo systemctl restart mysql。三、预防僵尸进程
wait()或waitpid()函数读取子进程的退出状态,回收资源。例如,在C语言中可通过waitpid(-1, &status, 0)等待所有子进程结束,或在循环中使用waitpid非阻塞检查(WNOHANG选项)。SIGCHLD信号处理:SIGCHLD信号处理函数,当子进程退出时自动调用waitpid()。示例代码(C语言):#include <signal.h>
#include <sys/wait.h>
void sigchld_handler(int s) {
while (waitpid(-1, NULL, WNOHANG) > 0); // 非阻塞回收所有子进程
}
int main() {
struct sigaction sa;
sa.sa_handler = sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGCHLD, &sa, NULL); // 注册信号处理函数
// ... 其他代码(如fork子进程)
}
```。
fork()两次:fork一个子进程,子进程再fork一个孙子进程后退出,孙子进程成为孤儿进程,由init进程接管,避免父进程未处理子进程退出导致的僵尸问题。cron定时任务、systemd服务),定期检查系统中的僵尸进程并自动清理。例如,创建zombie_cleaner.sh脚本:#!/bin/bash
zombies=$(ps -A -ostat,ppid,pid | grep -e '^[Zz]' | awk '{print $2}')
if [ -n "$zombies" ]; then
echo "$(date): Found $(echo "$zombies" | wc -l) zombie(s), cleaning..." >> /var/log/zombie_cleaner.log
echo "$zombies" | xargs -r kill -s SIGCHLD
fi
设置每5分钟运行一次:crontab -e,添加*/5 * * * * /path/to/zombie_cleaner.sh。