0

I have to kill/clean a zombie process in linux C. All I know is the PID of the zombie.

I'm creating a few zombie processes in a loop:

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

I can get their PID number using:

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

But how to kill/clean them using just the PID? I'm saving the PID in a variable and standard signal:

kill(PID,9) 

Doesn't even work, because the process is dead already. Any other way to achieve it? Please don't ask me why the hell I'm creating zombies to kill them later. It's not the case.

4

5 に答える 5

3

これは、すべてのゾンビプロセスを強制終了するために作成したスクリプトです。GDBデバッガーを使用して親プロセスに接続し、waitpidを送信してゾンビプロセスを強制終了します。これにより、親はライブのままになり、ゾンビのみが殺されます。

GDBデバッガーをインストールする必要があり、プロセスにアタッチするためのアクセス許可を使用してログインする必要があります。これはCentos6.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 "***********************************************************"

楽しみ。

于 2013-03-14T21:01:07.907 に答える
3

「ゾンビ」とは、すでに死んでいるプロセスです。もう一度殺すことはできません。

「ゾンビ」は、実際には、プロセスの終了ステータスを含むプロセス テーブル内の単なるエントリです。それを取り除くには、親プロセスが呼び出しwait()てその情報を取得する必要があります。または、親プロセス自体を終了することもできます。その後、子はいわゆる「孤児」になりinit、ID 1 のプロセスによって養子縁組されinitます。

于 2012-12-02T13:18:13.980 に答える
2

ゾンビはすでに死んでいるので、ゾンビを殺すことはできません。

それらがゾンビである理由は、プロセスが終了したが、親が終了コードを取得していないためです。

最終的initに、ゾンビが孤児になった場合にこれを行う必要があります。真のゾンビ (親はあるが、その親がまだ終了コードを取得していないプロセス) は、次のいずれかになるまで存続します。

  • 終了コードを収集します。また
  • 親が終了すると孤立します。
于 2012-12-02T13:19:10.997 に答える
1

あなたがしていることはかなりねじれているようです。最小限のテスト ケースを作成して、より広範な問題を示し、いずれにせよ答えようとしたと仮定します。フェザー プロセスがその子プロセス リソースをクリーンアップしない (waitpid とフレンズを呼び出す) と、ゾンビが作成されます。

したがって、父プロセスのコードを正しく記述して SIGCHLD に応答し、waitpid を呼び出すか、父プロセスを制御できない場合は、ここで推測しているように、父プロセスを強制終了します (SIGTERM を父プロセスに送信します)。

後者が機能する理由は、すべての父のない子供が、必要なクリーンアップを実行する init (PID 1) に再親化されるためです。

于 2012-12-02T13:19:32.783 に答える
0

SIGCHLD シグナルを使用してみることができます。たとえば、C の場合:

signal(SIGCHLD, handleSIGCHLD);


  void handleSIGCHLD(int signum) {
  int stat;

 /*Kills all the zombie processes*/
  while(waitpid(-1, &stat, WNOHANG) > 0);
}
于 2012-12-02T13:23:21.833 に答える