Что такое процесс <defunct> и почему его не убивают?

180

Браузер Chrome не реагировал, и я попытался убить его, но вместо того, чтобы исчезнуть, процесс имел <defunct>право и не был убит:

введите описание изображения здесь

Что <defunct>за процесс и почему его не убить?

Эдуард Флоринеску
источник
3
В принятом ответе упоминается, что « kill -9 PIDне работает». Отчасти это правда: на самом деле, НЕТ убийств не сработает. Кроме того, -9 следует использовать в качестве крайней меры. В 99% случаев уничтожение родительского процесса по умолчанию приведет к его уничтожению и получению всех дочерних процессов. «Убить по умолчанию» - это SIGTERM (-15). Я призываю поклонников -9 (SIGKILL) прочитать stackoverflow.com/questions/690415/…
Майк С

Ответы:

172

Из вашего вывода мы видим «несуществующий», что означает, что процесс либо завершил свою задачу, либо был поврежден или уничтожен, но его дочерние процессы все еще работают или эти родительские процессы отслеживают свой дочерний процесс. Чтобы убить такой процесс, kill -9 PID не работает. Вы можете попытаться убить их с помощью этой команды, но она будет показывать это снова и снова.

Определите, кто является родительским процессом этого несуществующего процесса, и уничтожьте его. Чтобы узнать это, запустите команду:

ps -ef | grep defunct

UID          PID     PPID       C    STIME      TTY          TIME              CMD
1000       637      27872      0   Oct12      ?        00:00:04 [chrome] <defunct>
1000      1808      1777       0    Oct04     ?        00:00:00 [zeitgeist-datah] <defunct>

Затем kill -9 637 27872, затем убедитесь, что несуществующий процесс прошел ps -ef | grep defunct.

Paddington
источник
13
Вы не можете убить "несуществующий" процесс. Вы можете только ускорить удаление его записи в таблице процессов, убив его родителя.
JFS
57
Что если ppid - это 1( init)? Предположим, мне просто нужно подождать?
Люк
7
чтобы автоматизировать уничтожение, вы также можете сделать это (возможно, потребуется изменить, какие байты вырезаете из выходных данных):ps -ef | grep defunct | grep -v grep | cut -b8-20 | xargs kill -9
warren
3
@ Warren Спасибо. Вы также можете сделать это немного короче и (imo) проще, не выполняя второй grep. Просто измените первый grep на grep [d]efunctаналогичный, и он не будет совпадать сам по себе.
Thor84no
4
@ warren, вы не можете убить несуществующий процесс - даже с SIGKILL. Кроме того, вы используете kill -9 довольно без разбора. См. Stackoverflow.com/questions/690415/… . Если вы хотите , чтобы убить несуществующие ребенок, вы можете попробовать: parents_of_dead_kids=$(ps -ef | grep [d]efunct | awk '{print $3}' | sort | uniq | egrep -v '^1$'); echo "$parents_of_dead_kids" | xargs kill. Повторите сценарий через 30 секунд или около того, kill -9если хотите. (Обратите внимание, что я специально запрещаю убийство Init)
Майк С
60

Страница руководства ps (1) гласит :

Отмеченные процессы <defunct>- это мертвые процессы (так называемые "зомби" ), которые остаются, потому что их родитель не уничтожил их должным образом. Эти процессы будут уничтожены, init(8)если родительский процесс завершится.

Вы не можете убить его, потому что он уже мертв. Остается только запись в таблице процессов :

В Unix и Unix-подобных компьютерных операционных системах процесс зомби или несуществующий процесс - это процесс, который завершил выполнение, но все еще имеет запись в таблице процессов. Эта запись все еще необходима для того, чтобы родительский процесс мог прочитать статус выхода своего дочернего процесса.

Нет ничего плохого в том, чтобы позволить таким процессам быть, если их не много. Зомби в конце концов пожинает его родитель (по вызову wait(2)). Если исходный родитель не получил его до своего выхода, initprocess ( pid == 1) сделает это позже. Зомби Процесс это просто:

Процесс, который завершился и который удален, когда его состояние завершения было сообщено другому процессу, который ожидает завершения этого процесса.

JFS
источник
1

Спасибо, Майк С. Мы взяли вашу строку и написали скрипт, который уничтожит несуществующие процессы, чьим родителем является in.telnetd. Мы не хотели, чтобы он уничтожал какой-либо родительский процесс, просто мы знаем, что telnetd вызывает проблему, и мы будем запускать его несколько раз, чтобы убить несколько, если это необходимо.

# egrep -v '^1$ = Make sure the process is not the init process.
# awk '{print $3}' = Print the parent process.

first_parent_of_first_dead_kid=$(ps -ef | grep [d]efunct | awk '{print $3}' | head -n1 | egrep -v '^1$')
echo "$first_parent_of_first_dead_kid"

# If the first parent of the first dead kid is in.telnetd, then kill it.
if ps -ef | grep $first_parent_of_first_dead_kid | grep in.telnetd;then
        echo "We have a defunct process whose parent process is in.telnetd" | logger -t KILL-DEFUNCT-TELNET
        echo "killing $first_parent_of_first_dead_kid" | logger -t KILL-DEFUNCT-TELNET
        kill $first_parent_of_first_dead_kid 2>&1 | logger -t KILL-DEFUNCT-TELNET
fi
Дэвид Браззил
источник
1

развивая ответ Паддингтона ..

Из вашего вывода мы видим несуществующий , что означает, что этот дочерний процесс либо выполнил свою задачу, либо был поврежден или уничтожен. Его родительский процесс все еще выполняется и не заметил своего мертвого потомка.

kill -9 PID не будет работать (уже мертв).

Чтобы определить родителя этого дочернего процесса, выполните следующую команду:

ps -ef | grep defunct

 UID  PID **PPID** C STIME TTY TIME     CMD
 1000 637  27872   0 Oct12 ?   00:00:04 [chrome] <defunct>

Посмотрите, кто является родителем: ps ax | grep 27872

Если вы хотите, вы можете убить родителя, и несуществующий исчезнет. kill -9 27872

см. ответ Дж.Ф. Себастьяна для более технических рассуждений.

kevinf
источник
1

В дополнение к ответу @ Paddington я добавил эту функцию в свой bashrc для быстрой проверки:

defunct(){
    echo "Children:"
    ps -ef | head -n1
    ps -ef | grep defunct
    echo "------------------------------"
    echo "Parents:"
    ppids="$(ps -ef | grep defunct | awk '{ print $3 }')"
    echo "$ppids" | while read ppid; do
        ps -A | grep "$ppid"
    done
}

Это выводит что-то вроде:

Дети:
UID PID PPID C STIME TTY TIME CMD
пользователь 25707 25697 0 фев 26 баллов / 0 00:00:00 [sh] 
пользователь 30381 29915 0 11:46 баллов / 7 00:00:00 grep defunct
------------------------------
Родители:
25697 баллов / 0 00:00:00 вечера
aggregate1166877
источник