Убить зомби-процесс, зная PID в linux C

Мне нужно убить/очистить процесс зомби в 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) 

Даже не работает, потому что процесс уже мертв. Любой другой способ добиться этого? Пожалуйста, не спрашивайте меня, какого черта я создаю зомби, чтобы убить их позже. Это не так.


person krzakov    schedule 02.12.2012    source источник
comment
Прочитайте это: linuxsa.org.au/tips/zombies.html   -  person Thomas    schedule 02.12.2012
comment
@Rajesh У меня нет PID родителей, я использую bash для создания.   -  person krzakov    schedule 02.12.2012
comment
@Раджеш sudo kill -KILL 1, чтобы быть уверенным.   -  person Daniel Fischer    schedule 02.12.2012
comment
@DanielFischer нет ничего лучше, чем тянуть кабель питания;)   -  person    schedule 02.12.2012
comment
@Rajesh Раджеш, мне пришлось бы оставить клавиатуру для этого. И я слышал, что этот метод не работает так надежно на ноутбуках.   -  person Daniel Fischer    schedule 02.12.2012
comment
@DanielFischer, я слышал, что металлическая полоса в порту USB работает даже лучше.   -  person    schedule 02.12.2012


Ответы (5)


Вот скрипт, который я создал, чтобы убить ВСЕ зомби-процессы. Он использует отладчик GDB для подключения к родительскому процессу и отправляет ожидание, чтобы убить процесс-зомби. Это оставит родителя живым и убьет только зомби.

Отладчик 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 "***********************************************************"

Наслаждаться.

person Mitch Milner    schedule 14.03.2013
comment
Если вы можете опубликовать точно один и тот же ответ на два вопроса, это признак того, что вопросы дублируются. Вместо того, чтобы публиковать второй ответ, вы должны отметить (или проголосовать), чтобы закрыть его как дубликат. - person ChrisF; 15.03.2013

«Зомби» — это уже мертвый процесс. Вы не можете убить его снова.

На самом деле «зомби» — это просто запись в таблице процессов, содержащая статус завершения процесса. Чтобы избавиться от нее, родительский процесс должен вызвать wait() для получения этой информации. В качестве альтернативы родительский процесс может завершиться сам; затем ребенок становится так называемым «сиротой» и усыновляется init, процессом с идентификатором 1. init автоматически пожинает всех мертвых детей.

person melpomene    schedule 02.12.2012
comment
Но как это сделать. У меня нет родительского PID. Я использую bash для создания зомби. - person krzakov; 02.12.2012
comment
Почему бы вам просто не перестать создавать зомби? - person melpomene; 02.12.2012
comment
Потому что мой клиент хочет их иметь. Это немного грязно, но я должен создать их удаление. - person krzakov; 02.12.2012
comment
Пожалуйста, прочитайте конец первого вопроса :) - person krzakov; 02.12.2012
comment
Я не прошу веселья. Эта информация на самом деле определяет решение, которое вы собираетесь получить (потому что сейчас довольно неясно, в чем проблема на самом деле). - person melpomene; 02.12.2012
comment
Все, что мне нужно сделать, это создать определенное количество зомби (поэтому я использую для этого цикл), а затем мне нужно выяснить, как убить зомби (одного из них), используя его PID. - person krzakov; 02.12.2012
comment
Клиент хочет этого. Не имеет значения. - person krzakov; 02.12.2012
comment
Клиент может хотеть до посинения – он не может получить то, что невозможно. Единственный способ, которым эти зомби уходят, - это если их статус выхода пожинается, и если родитель этого не делает, то они будут торчать до тех пор, пока родитель не умрет, и init пожинает их. Похоже, вам придется отступить и найти другой подход к основной проблеме. - person Norman Gray; 02.12.2012

Вы правы, вы не можете убить зомби, потому что они уже мертвы.

Причина, по которой они являются зомби, заключается в том, что процесс завершился, но родитель не получил код выхода.

В конце концов, init должен сделать это за вас, если и когда зомби станет сиротой. Настоящий зомби, процесс, у которого все еще есть родитель, но этот родитель еще не собрал код выхода, будет существовать до тех пор, пока:

  • родитель собирает код выхода; или
  • он становится сиротой, когда родитель выходит.
person paxdiablo    schedule 02.12.2012
comment
Должен быть способ очистить этот беспорядок. - person krzakov; 02.12.2012

То, что вы делаете, кажется довольно извращенным. Я предполагаю, что вы попытались создать минимальный тестовый пример, чтобы показать более широкую проблему и в любом случае ответить. Зомби создается, когда процесс пера не очищает (вызывает waitpid и друзей) ресурсы своего дочернего процесса.

Итак, либо напишите код родительского процесса правильно, чтобы он отвечал на SIGCHLD и вызывал waitpid, либо, если у вас нет контроля над родительским процессом, как я предполагаю, здесь дело обстоит так, уничтожьте родительский процесс (отправьте SIGTERM отцу).

Причина, по которой последний будет работать, заключается в том, что все дети без отца переназначаются для инициализации (PID 1), которая будет выполнять необходимую очистку.

person gby    schedule 02.12.2012
comment
У меня действительно нет родительского PID. Вы предлагаете убить процесс инициализации? - person krzakov; 02.12.2012
comment
@krzakov, не даже думайте о малейшей возможности попытаться убить процесс init. - person paxdiablo; 02.12.2012

Вы можете попробовать использовать сигнал SIGCHLD. Например, в C:

signal(SIGCHLD, handleSIGCHLD);


  void handleSIGCHLD(int signum) {
  int stat;

 /*Kills all the zombie processes*/
  while(waitpid(-1, &stat, WNOHANG) > 0);
}
person Fyre    schedule 02.12.2012
comment
Но в моей программе я должен убить зомби только по его PID. Не все они. - person krzakov; 02.12.2012
comment
@krzakov Вы не можете убивать зомби; они уже мертвы. - person melpomene; 02.12.2012
comment
О да ладно. Убить/очистить что угодно. - person krzakov; 02.12.2012