【问题标题】:Killing zombie process, knowing PID in linux C [duplicate]杀死僵尸进程,知道linux C中的PID [重复]
【发布时间】:2012-12-02 13:13:23
【问题描述】:

我必须在 linux C 中杀死/清理一个僵尸进程。我只知道僵尸的 PID。

我正在循环中创建一些僵尸进程:

int i = 0;
for (i; i<5; i++)
{
  system("(: & exec sleep 30) &"); // create zombie for 30 sec
}

我可以使用以下方法获取他们的 PID 号:

system("ps aux | awk '{ print $8 " " $2 }' | grep -w Z");

但是如何仅使用 PID 来杀死/清理它们? 我将 PID 保存在变量和标准信号中:

kill(PID,9) 

甚至不起作用,因为进程已经死了。 还有其他方法可以实现吗?请不要问我为什么要制造僵尸来杀死他们。事实并非如此。

【问题讨论】:

  • @Rajesh 我没有父母的 PID,使用 bash 创建。
  • @Rajesh sudo kill -KILL 1 确定。
  • @DanielFischer 没有什么比拔电源线更好的了;)
  • @Rajesh 我将不得不为此离开键盘。而且我听说这种方法在笔记本电脑上并不可靠。

标签: c linux process zombie-process


【解决方案1】:

这是我创建的用于杀死所有僵尸进程的脚本。它使用 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 "***********************************************************"

享受吧。

【讨论】:

  • 如果您可以完全对两个问题发布相同的答案,则表明这些问题是重复的。而不是发布第二个答案,您应该标记(或投票)作为重复关闭。
【解决方案2】:

“僵尸”是一个已经死亡的进程。你不能再杀了它。

“僵尸”实际上只是进程表中的一个条目,其中包含进程的退出状态。为了摆脱它,父进程必须调用wait() 来检索该信息。或者,父进程可以自行退出;然后孩子成为所谓的“孤儿”并被init收养,ID为1的进程。init自动收割所有死去的孩子。

【讨论】:

  • 但是怎么做呢。我没有父 PID。我正在使用 bash 创建僵尸。
  • 你为什么不从一开始就停止制造僵尸?
  • 因为我的客户想拥有它们。这有点乱,但我必须创建一个删除它们。
  • 请阅读第一个问题的结尾:)
  • 我不是在找乐子。这些信息实际上决定了您将获得的解决方案(因为现在还不清楚问题到底是什么)。
【解决方案3】:

你说得对,你不能杀死僵尸,因为它们已经死了。

他们是僵尸的原因是因为进程已经完成,但父进程没有收获退出代码。

最终,当僵尸变成孤儿时,init 应该为您执行此操作。真正的僵尸进程,即仍然有父进程但父进程尚未获取退出代码的进程,将持续到以下任一情况:

  • 确实获取退出代码;或
  • 当父级退出时,它变成一个孤儿。

【讨论】:

  • 必须是清理这个烂摊子的方法。
【解决方案4】:

你正在做的事情似乎很扭曲。我将假设您已尝试创建一个最小的测试用例来显示更广泛的问题并无论如何都要回答 - 当羽化进程未清理(调用 waitpid 和朋友)其子进程资源时会创建僵尸。

所以,要么正确地编写父进程代码以响应 SIGCHLD 并调用 waitpid,或者,如果您无法控制父进程,我猜就是这里的情况,杀死父进程(向父进程发送 SIGTERM )。

后者起作用的原因是所有没有父亲的孩子都被重新设置为 init (PID 1),它将执行所需的清理。

【讨论】:

  • 我真的没有父 PID。你建议杀死初始化进程?
  • @krzakov,不要不要考虑尝试杀死init进程的最简单的可能性。
【解决方案5】:

您可以尝试使用 SIGCHLD 信号。例如在 C 语言中:

signal(SIGCHLD, handleSIGCHLD);


  void handleSIGCHLD(int signum) {
  int stat;

 /*Kills all the zombie processes*/
  while(waitpid(-1, &stat, WNOHANG) > 0);
}

【讨论】:

  • 但是在我的程序中,我必须通过僵尸的 PID 来杀死它。不是全部。
  • @krzakov 你不能杀死僵尸;他们已经死了。
  • 哦,拜托。杀死/清理任何东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-01
  • 2013-06-25
  • 1970-01-01
  • 2011-09-14
  • 2014-06-19
  • 1970-01-01
  • 2021-12-09
相关资源
最近更新 更多