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


180

Хромований браузер не реагував, і я намагався його вбити, але замість того, щоб зникнути, процес мав <defunct>праворуч, і його не вбили:

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

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


3
У прийнятій відповіді зазначається, що " kill -9 PIDне працює". Частково це правда: насправді НЕ вбиватиметься. Крім того, -9 слід використовувати в крайньому випадку. У 99% випадків вбивство батьківського процесу за замовчуванням вбиває його І пожинає всіх дітей. "Убити" за замовчуванням "є SIGTERM (-15). Я закликаю шанувальників -9 (SIGKILL) читати stackoverflow.com/questions/690415/…
Mike S

Відповіді:


172

З вашого результату ми бачимо "неіснуючий", який означає, що процес або виконав своє завдання, або був пошкоджений або вбитий, але його дочірні процеси все ще працюють або цей батьківський процес контролює його дочірній процес. Для вбивства подібного процесу вбити -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.


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 [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)
Mike S

60

Сторінка посібника ps (1) говорить :

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

Ви не можете його вбити, бо він уже мертвий. Залишилося лише запис у таблиці процесів :

У Unix та Unix-подібних комп'ютерних операційних системах процес зомбі або неіснуючий процес - це процес, який завершив виконання, але все ще має запис у таблиці процесів. Цей запис все ще необхідний для того, щоб батьківський процес міг прочитати статус виходу дитини.

Не допустити таких процесів шкоди, якщо їх багато. Зрештою, зомбі пожинає батьком (дзвонивши wait(2)). Якщо оригінальний батько ще не отримав його до власного виходу, то initобробка ( pid == 1) робить це пізніше. Процес зомбі :

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


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

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


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 deunct
------------------------------
Батьки:
25697 балів / 0 00:00:00 нм
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.