【发布时间】:2011-09-14 05:03:51
【问题描述】:
有没有办法杀死僵尸进程?我试过调用exit 来终止进程,甚至向进程发送SIGINT 信号,但似乎没有什么可以杀死它。我正在为 Linux 编程。
【问题讨论】:
-
哦,我忘了开一个明显的玩笑:杀死僵尸的方法是在头部开枪。
标签: c linux zombie-process
有没有办法杀死僵尸进程?我试过调用exit 来终止进程,甚至向进程发送SIGINT 信号,但似乎没有什么可以杀死它。我正在为 Linux 编程。
【问题讨论】:
标签: c linux zombie-process
如果我没记错的话,杀死僵尸进程的父进程将使僵尸进程死亡。
使用ps faux 获得一个显示父/子关系的运行进程的漂亮层次树。
【讨论】:
init收割。
僵尸进程是其父进程尚未等待的进程 ID(以及相关的终止状态和资源使用信息)。消除它的唯一方法是让其父级等待它(有时这可以通过手动向父级发送SIGCHLD 来实现,如果父级只是有问题并且有竞争条件而错过了等待的机会)但是通常,除非您强行终止父级,否则您会很不走运。
编辑:另一种方法,如果您绝望并且不想杀死父级,则使用 gdb 附加到父级并在僵尸子级上强制调用waitpid。
【讨论】:
参见unix-faqs“我如何摆脱顽固的僵尸进程?”
你不能杀死僵尸,因为它们已经死了。但是如果你有太多的僵尸然后杀死父进程或重新启动服务。
你可以尝试使用它的pid杀死僵尸进程
kill -9 pid
请注意,kill -9 并不能保证杀死僵尸进程
【讨论】:
kill -9 永远无法杀死僵尸进程。
僵尸进程已经死了,所以它们不能被杀死,只能被收割,这必须由它们的父进程通过wait*() 来完成。这通常称为child reaper 成语,在SIGCHLD 的信号处理程序中:
while (wait*(... WNOHANG ...)) {
...
}
【讨论】:
zombie、dead、killed 和child reaper :)
SIGCHLD 处理程序中,你可能会被阻塞并且永远不会返回。
WNOHANG 的 wait() 变体之一
signal(SIGCHLD, SIG_IGN) 让父进程忽略子进程。子进程一退出就消失(不留下僵尸),因为父进程已对其子进程的健康缺乏兴趣。
kill -17 ZOMBIE_PID
或
kill -SIGCHLD ZOMBIE_PID
可能会起作用,但就像其他人所说的那样,它正在等待父母打电话给wait(),所以除非父母没有收割而死,并且由于某种原因卡在那里你可能不想杀死它。
【讨论】:
这是我创建的用于杀死所有僵尸进程的脚本。它使用 GDB 调试器附加到父进程并发送一个 waitpid 来杀死僵尸进程。这将使父母活着,只会杀死僵尸。
需要安装 GDB 调试器,并且您需要以附加到进程的权限登录。这已经在 Centos 6.3 上进行了测试。
#!/bin/bash
##################################################################
# Script: Zombie Slayer
# Author: Mitch Milner
# Date: 03/13/2013 ---> A good day to slay zombies
#
# Requirements: yum install gdb
# permissions to attach to the parent process
#
# This script works by using a debugger to
# attach to the parent process and then issuing
# a waitpid to the dead zombie. This will not kill
# the living parent process.
##################################################################
clear
# Wait for user input to proceed, give user a chance to cancel script
echo "***********************************************************"
echo -e "This script will terminate all zombie process."
echo -e "Press [ENTER] to continue or [CTRL] + C to cancel:"
echo "***********************************************************"
read cmd_string
echo -e "\n"
# initialize variables
intcount=0
lastparentid=0
# remove old gdb command file
rm -f /tmp/zombie_slayer.txt
# create the gdb command file
echo "***********************************************************"
echo "Creating command file..."
echo "***********************************************************"
ps -e -o ppid,pid,stat,command | grep Z | sort | while read LINE; do
intcount=$((intcount+1))
parentid=`echo $LINE | awk '{print $1}'`
zombieid=`echo $LINE | awk '{print $2}'`
verifyzombie=`echo $LINE | awk '{print $3}'`
# make sure this is a zombie file and we are not getting a Z from
# the command field of the ps -e -o ppid,pid,stat,command
if [ "$verifyzombie" == "Z" ]
then
if [ "$parentid" != "$lastparentid" ]
then
if [ "$lastparentid" != "0" ]
then
echo "detach" >> /tmp/zombie_slayer.txt
fi
echo "attach $parentid" >> /tmp/zombie_slayer.txt
fi
echo "call waitpid ($zombieid,0,0)" >> /tmp/zombie_slayer.txt
echo "Logging: Parent: $parentid Zombie: $zombieid"
lastparentid=$parentid
fi
done
if [ "$lastparentid" != "0" ]
then
echo "detach" >> /tmp/zombie_slayer.txt
fi
# Slay the zombies with gdb and the created command file
echo -e "\n\n"
echo "***********************************************************"
echo "Slaying zombie processes..."
echo "***********************************************************"
gdb -batch -x /tmp/zombie_slayer.txt
echo -e "\n\n"
echo "***********************************************************"
echo "Script complete."
echo "***********************************************************"
享受吧。
【讨论】:
warning: /tmp/zombie_slayer.txt: No such file or directory。