Wie finde ich Zombie-Prozess?

100
System information as of Fri Mar  9 19:40:01 KST 2012

  System load:    0.59               Processes:           167
  Usage of /home: 23.0% of 11.00GB   Users logged in:     1
  Swap usage:     0%                 IP address for eth1: 192.168.0.1

  => There is 1 zombie process.

  Graph this data and manage this system at https://landscape.canonical.com/

10 packages can be updated.
4 updates are security updates.

Last login: Fri Mar  9 10:23:48 2012
a@SERVER:~$ ps auxwww | grep 'Z'
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
usera     13572  0.0  0.0   7628   992 pts/2    S+   19:40   0:00 grep --color=auto Z
a@SERVER:~$ 

Wie finde ich diesen Zombie-Prozess?

Pablo
quelle
Warum öffnen Sie nicht den Systemmonitor und suchen nach dem Zombie-Prozess?
dlin
8
Wie geht das auf einem kopflosen No-X-Server?
SabreWolfy
2
Überraschend, dass keine Antwort unten tatsächlich besagt, dass es keinen Zombie-Prozess im System gibt, der auf der obigen Ausgabe basiert. Wenn es wirklich einen gab, hätte der ps auxwww | grep 'Z'Befehl einen Prozess in einem ZZustand anzeigen sollen . Das Sprichwort "Systeminformationen" => There is 1 zombie process.scheint ein Fehler zu sein. Entweder das, oder es fehlen Informationen in der Frage.
Arielf

Antworten:

126

Um einen Zombie (Prozess) zu töten, muss man seinen übergeordneten Prozess (genau wie echte Zombies!) Töten, aber die Frage war, wie man ihn findet.

Finde den Zombie (Die Frage beantwortete diesen Teil):

a@SERVER:~$ ps aux | grep 'Z'

Was du bekommst, sind Zombies und alles andere mit einem Z, also bekommst du auch das grep:

USER       PID     %CPU %MEM  VSZ    RSS TTY      STAT START   TIME COMMAND
usera      13572   0.0  0.0   7628   992 pts/2    S+   19:40   0:00 grep --color=auto Z
usera      93572   0.0  0.0   0      0   ??       Z    19:40   0:00 something

Finde die Eltern des Zombies:

a@SERVER:~$ pstree -p -s 93572

Werde dir geben:

init(1)---cnid_metad(1311)---cnid_dbd(5145)

In diesem Fall möchten Sie diesen übergeordneten Prozess nicht beenden, und Sie sollten mit einem Zombie zufrieden sein. Wenn Sie jedoch den unmittelbaren übergeordneten Prozess 5145 beenden, wird dieser Prozess möglicherweise nicht mehr ausgeführt.

Zusätzliche Ressourcen auf askubuntu:

Duncanmoo
quelle
1
Das Ergebnis, das Sie in Ihrer Antwort sehen, ist der Befehl grep selbst, nicht der Zombie-Prozess. Es ist die gleiche Fehlinterpretation, die Pablo in seiner Antwort gemacht hat. Die Antwort von Rinzwind unten sucht tatsächlich nach dem Zombie-Prozess und listet sie auf. Eine andere Möglichkeit könnte sein, nach "nicht mehr existierend" zu
suchen
pstree -H your_desired_pid -p
Greg M. Krsak
Vielen Dank an Greg, der zur Diskussion beigetragen hat, aber bitte denken Sie daran, dass dies eine Hilfeseite ist. Das Einfügen eines Befehls ohne Erklärung ist für die meisten Leute, die hierher kommen, um Hilfe zu suchen, nicht hilfreich.
Duncanmoo
1
Das ist eine großartige Antwort! Es ist noch heute gültig! Ich konnte meinen Zombie-Prozess finden und seinen übergeordneten Prozess ohne Probleme beenden. Danke!
Terrance
1
Wenn Sie pstree nicht installiert haben, tun Sie ps wauxfdasselbe
JDS
35

Obwohl diese Frage alt ist, dachte ich, dass jeder eine zuverlässigere Antwort verdient:

ps axo pid=,stat=

Dadurch werden zwei durch Leerzeichen getrennte Spalten ausgegeben, von denen die erste eine PID und die zweite deren Status ist.

Ich denke nicht einmal GNU psbietet eine Möglichkeit, direkt nach Status zu filtern, aber Sie können dies zuverlässig tunawk

ps axo pid=,stat= | awk '$2~/^Z/ { print }'

Sie haben jetzt eine Liste von PIDs, die Zombies sind. Da Sie den Status kennen, muss er nicht mehr angezeigt werden, damit er herausgefiltert werden kann.

ps axo pid=,stat= | awk '$2~/^Z/ { print $1 }'

Geben einer durch Zeilenumbrüche getrennten Liste von Zombie-PIDs.

Sie können diese Liste jetzt mit einer einfachen Shell-Schleife bearbeiten

for pid in $(ps axo pid=,stat= | awk '$2~/^Z/ { print $1 }') ; do
    echo "$pid" # do something interesting here
done

ps ist ein leistungsfähiges Tool und Sie müssen nichts kompliziertes tun, um Prozessinformationen daraus zu erhalten.

(Bedeutung der verschiedenen Prozesszustände hier - https://unix.stackexchange.com/a/18477/121634 )

Sorpigal
quelle
2
awkist auch ein leistungsfähiges Werkzeug, das nicht nur Text teilt, sondern auch mit diesem übereinstimmt. +1 ... die anderen verwendet, grepwo es unnötig und ungenau ist.
0xC0000022L
Jetzt habe ich eine Liste der Zombie-Prozesse. Wie töte ich sie?
Chovy
@chovy: Das hängt davon ab, beinhaltet aber im Allgemeinen das Töten oder Signalisieren des Elternteils. Andere Antworten hier gehen darauf ein. In der oben gezeigten Schleife finden Sie die übergeordnete PID wie ps -p "$pid" -opid=,ppid=
folgt
Wenn ich das übergeordnete Element will, tötet es dann nicht alle seine untergeordneten Prozesse? Ich möchte nur den einen Zombie-Prozess beenden. Ich kenne das ppid.
Chovy
1
Ich schlage vor ppid=, die Optionsliste zu erweitern, sodass kein separater Befehl zum Abrufen von ppid erforderlich ist.
Ding-Yi Chen
3

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

Von: http://www.cyberciti.biz/tips/killing-zombie-process.html

Aus den Kommentaren ein verbesserter:

for p in $(ps jauxww | grep Z | grep -v PID | awk '{print $3}'); do
    for every in $(ps auxw | grep $p | grep cron | awk '{print $2}'); do
        kill -9 $every;
    done;
done;

Achtung: Dieser tötet auch die Prozesse.

Rinzwind
quelle
gibt immer noch nichts zurück. Ich denke, mein Weg war auch nicht falsch.
Pablo
Das zweite Beispiel ist höllisch unzuverlässig und das erste ist unnötig ausführlich (versuchen Sie es ps axo pid=,stat= | awk '$2~/Z/ {print $1}'stattdessen).
Sorpigal
3

Weniger ist mehr:

ps afuwwx | less +u -p'^(\S+\s+){7}Z.*'

Geben Sie mir also eine Gesamtstruktur (einen Baum) der Prozesse aller Benutzer in einem benutzerorientierten Format mit unbegrenzter Breite auf einem beliebigen Tty und zeigen Sie es mir auf einem halben Bildschirm darüber, wo es mit dem Fall übereinstimmt, dass die achte Spalte ein Z und enthält warum nicht die ganze Zeile markieren.

Benutzerorientiertes Format scheint zu bedeuten: USER, PID, %CPU, %MEM, VSZ, RSS, TTY, STAT, START, TIME, COMMANDDer Zombie-Status wird in der 8. Spalte angezeigt.

Sie können ein Nvor dem einwerfen, pwenn Sie Zeilennummern möchten, und ein, Jwenn Sie ein Sternchen bei der Übereinstimmung möchten. Leider, wenn Sie Gdie Zeile nicht markieren, die der Stern nicht anzeigt, obwohl er JPlatz dafür schafft.

Am Ende erhalten Sie etwas, das wie folgt aussieht:

…
  root      2919  0.0  0.0  61432  5852 ?      Ss Jan24 0:00 /usr/sbin/sshd -D
  root     12984  0.0  0.1 154796 15708 ?      Ss 20:20 0:00  \_ sshd: lamblin [priv]
  lamblin  13084  0.0  0.0 154796  9764 ?      S  20:20 0:00      \_ sshd: lamblin@pts/0
* lamblin  13086  0.0  0.0  13080  5056 pts/0  Z  20:20 0:00          \_ -bash <defunct>
  lamblin  13085  0.0  0.0  13080  5056 pts/0  Ss 20:20 0:00          \_ -bash
  root     13159  0.0  0.0 111740  6276 pts/0  S  20:20 0:00              \_ su - nilbmal
  nilbmal  13161  0.2  0.0  13156  5004 pts/0  S  20:20 0:00                  \_ -su
  nilbmal  13271  0.0  0.0  28152  3332 pts/0  R+ 20:20 0:00                      \_ ps afuwwx
  nilbmal  13275  0.0  0.0   8404   848 pts/0  S+ 20:20 0:00                      \_ less +u -Jp^(\S+\s+){7}Z.*
…

Sie könnten dies mit (und es wird feststellen, ob Ihr Terminal -U Unicode oder -A Ascii mag):

pstree -psS <PID LIST>

ODER verwenden Sie einfach den Aufwärtspfeil less, um diesem Baum / dieser Gesamtstruktur durch die Hierarchie zu folgen. Das ist, was ich mit dem Ansatz "Weniger ist mehr" empfohlen habe.

dlamblin
quelle
0

Ich schlage Ihnen diesen Befehl vor:

ps aux | awk '"[Zz]" ~ $8 { printf("%s, PID = %d\n", $8, $2); }'
Peycho Dimitrov
quelle
Mit auxund munging Strings aus ist es unnötig unzuverlässig , wenn Sie verwenden können , -ound fordern Sie genau das, was Sie wollen. Verwenden Sie ps ax -o pid=,stat= | awk '$2 ~ "[Zz]" { printf("%s, PID = %d\n", $2, $1); }'stattdessen.
Sorpigal
-1

Führen Sie den folgenden Befehl aus, um Prozesszombies aufzulisten:

ps j | awk '$7 ~ "Z"'

$7Je nach Betriebssystem müssen Sie möglicherweise Änderungen vornehmen.

Dadurch wird auch die Liste der übergeordneten Prozess-IDs ( PPID) zurückgegeben.

Um zu versuchen, die Zombies zu töten (nach dem Testen des obigen Befehls), versuchen Sie:

kill -9 $(ps j | awk 'NR>1 && $7 ~ "Z" {print $2}')

Um ihre Eltern zu identifizieren, versuchen Sie es mit pstree:

$ ps j | awk 'NR>1 && $7 ~ "T" {print $2}' | xargs -L1 pstree -sg
systemd(1)───sshd(1036)───sshd(2325)───sshd(2325)───bash(2383)───zombie(2430)
systemd(1)───sshd(1036)───sshd(2325)───sshd(2325)───bash(2383)───zombie(2431)
systemd(1)───sshd(1036)───sshd(2325)───sshd(2325)───bash(2383)───zombie(2432)
Kenorb
quelle
Es jist unnötig kompliziert, eine Spalte aus dem Format zu entfernen . Verwenden Sie -o, um stattdessen auszuwählen, was Sie möchten.
Sorpigal
2
ps jdruckt nicht alle Prozesse im System. Es werden nur die aktuellen Benutzer-Prozesse aufgelistet (im BSD-Jobstil), sodass möglicherweise Zombie-Prozesse übersehen werden.
Arielf