Co to jest <niedziałający> proces i dlaczego nie zostaje zabity?

180

Przeglądarka Chrome nie reagowała i próbowałem ją zabić, ale zamiast zniknąć proces miał <defunct>rację i nie został zabity:

wprowadź opis zdjęcia tutaj

Co to jest <defunct>za proces i dlaczego nie zostaje zabity?

Eduard Florinescu
źródło
3
Akceptowana odpowiedź mówi, że „ kill -9 PIDnie działa”. To częściowo prawda: w rzeczywistości ŻADNE zabójstwo nie zadziała. Poza tym, -9 powinno być użyte w ostateczności. 99% czasu domyślne zabijanie procesu nadrzędnego zabije go I zbierze wszystkie dzieci. „Domyślnym zabiciem” jest SIGTERM (-15). Zachęcam fanów -9 (SIGKILL) do przeczytania stackoverflow.com/questions/690415/…
Mike S

Odpowiedzi:

172

Z twoich danych wyjściowych widzimy „nieistniejący”, co oznacza, że ​​proces zakończył swoje zadanie lub został uszkodzony lub zabity, ale jego procesy potomne są nadal uruchomione lub te procesy nadrzędne monitorują proces potomny. Aby zabić tego rodzaju proces, kill -9 PID nie działa. Możesz spróbować zabić ich za pomocą tego polecenia, ale będzie to pokazywać to wielokrotnie.

Określ, który jest nadrzędny dla tego nieistniejącego procesu, i zabij go. Aby to wiedzieć, uruchom polecenie:

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>

Następnie kill -9 637 27872sprawdź, czy nieistniejący proces minął ps -ef | grep defunct.

Paddington
źródło
13
nie możesz zabić „nieistniejącego” procesu. Możesz przyspieszyć usuwanie wpisu w tabeli procesów, zabijając jego rodzica.
jfs
57
Co jeśli ppid to 1( init)? Załóżmy, że będę musiał tylko poczekać?
Luc
7
aby zautomatyzować zabijanie, możesz to również zrobić (być może trzeba będzie zmienić bajty, które wycinasz z wyjścia):ps -ef | grep defunct | grep -v grep | cut -b8-20 | xargs kill -9
warren
3
@warren Thanks. Możesz także uczynić to nieco krótszym i (imo) prostszym, nie robiąc drugiego grepa. Po prostu zmień pierwszy grep na grep [d]efunctlub podobny i nie będzie pasował do siebie.
Thor84no
4
@warren nie możesz zabić nieczynnego procesu - nawet przy pomocy SIGKILL. Co więcej, zabijasz -9 całkiem niedyskryminacyjnie. Zobacz stackoverflow.com/questions/690415/… . Jeśli chcesz zabić nieistniejącego dzieci, możesz spróbować: parents_of_dead_kids=$(ps -ef | grep [d]efunct | awk '{print $3}' | sort | uniq | egrep -v '^1$'); echo "$parents_of_dead_kids" | xargs kill. Uruchom skrypt ponownie po około 30 sekundach, kill -9jeśli chcesz. (Uwaga, szczególnie zabraniam zabijania Init)
Mike S
60

Strona podręcznika ps (1) mówi :

Oznaczone procesy <defunct>to martwe procesy (tak zwane „zombie” ), które pozostają, ponieważ ich rodzic nie zniszczył ich odpowiednio. Procesy te zostaną zniszczone, init(8)jeśli proces macierzysty wyjdzie.

Nie możesz go zabić, ponieważ jest już martwy. Pozostaje tylko wpis w tabeli procesów :

W systemach operacyjnych Unix i podobnych do Unixa proces zombie lub proces zlikwidowany to proces, który zakończył wykonywanie, ale nadal ma wpis w tabeli procesów. Ten wpis jest nadal potrzebny, aby proces macierzysty mógł odczytać status wyjścia swojego dziecka.

Pozwolenie na takie procesy nie jest szkodliwe, chyba że jest ich wiele. Zombie zostaje ostatecznie zebrane przez swojego rodzica (przez telefon wait(2)). Jeśli pierwotny rodzic nie wykorzystał go przed własnym wyjściem, wówczas initproces ( pid == 1) zrobi to później. Proces Zombie to po prostu:

Proces, który się zakończył i który jest usuwany, gdy jego status wyjścia został zgłoszony do innego procesu, który czeka na zakończenie tego procesu.

jfs
źródło
1

Dziękuję Mike S. Wzięliśmy twój wiersz i napisaliśmy skrypt, który zabije nieczynne procesy, których rodzicem jest in.telnetd. Nie chcieliśmy, aby zabijał jakikolwiek proces nadrzędny, po prostu telnetd, o którym wiemy, że powoduje problem, i uruchomimy go wiele razy, aby zabić wiele z nich w razie potrzeby.

# 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
David Brazzeal
źródło
1

rozwijając odpowiedź Paddingtona ...

Z twoich danych wyjściowych widzimy nieistniejące , co oznacza, że ​​ten proces potomny zakończył swoje zadanie lub został uszkodzony lub zabity. Proces nadrzędny wciąż trwa i nie zauważył martwego dziecka.

kill -9 PID nie zadziała (już nie żyje).

Aby ustalić element nadrzędny tego procesu potomnego, uruchom następującą komendę:

ps -ef | grep defunct

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

Zobacz, kto jest rodzicem: ps ax | grep 27872

Jeśli chcesz, możesz zabić rodzica, a nieżyjący odejdzie. kill -9 27872

zobacz odpowiedź JF Sebastiana, by uzyskać bardziej techniczne uzasadnienie.

kevinf
źródło
1

Dodając do odpowiedzi @ Paddington, dodałem tę funkcję do mojego bashrc w celu szybkiego sprawdzenia:

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
}

Wyprowadza coś takiego:

Dzieci:
UID PID PPID C STIME TTY TIME CMD
użytkownik 25707 25697 0 lutego 26 pkt / 0 00:00:00 [sh] 
użytkownik 30381 29915 0 11:46 pkt / 7 00:00:00 grep nie działa
------------------------------
Rodzice:
25697 pkt / 0 00:00:00 npm
aggregate1166877
źródło