Warum Prozess / Programm wird Zombie?

13

Wenn das Skript über die Befehlszeile einwandfrei ausgeführt wird, warum wird dasselbe Skript nach dem Ausführen von cron in den Zombie-Status versetzt und wie können Sie das Problem beheben?

Hier folgendes reales Beispiel:

[root@abc ~]# ps ax | grep Z
23880 ?        Zs     0:00 [checkloadadv.sh] <defunct>
23926 pts/0    S+     0:00 grep Z
[root@abc ~]# strace -p 23880
attach: ptrace(PTRACE_ATTACH, ...): Operation not permitted
[root@abc ~]# pstree | grep  checkload
init-+-crond---crond-+-checkloadadv.sh
[root@abc ~]# bash /usr/bin/checkloadadv.sh
System Load is OK : 0.05
Rahul Patil
quelle
Fehlerbehebung tritt auf, wenn Probleme auftreten. Zombies sind keine Probleme.
Gilles 'SO- hör auf böse zu sein'
@ Gilles, du hast recht, aber muss ich mich darum kümmern und sie verhindern? was denkst du ?
Rahul Patil
Sie sind keine Probleme, also brauchen Sie sich nicht darum zu kümmern.
Gilles 'SO- hör auf böse zu sein'

Antworten:

21

Bildbeschreibung hier eingeben

Wie bei echten Zombies kann ein Zombie-Prozess nicht getötet werden, weil er bereits tot ist.

Wie es passiert

Wenn unter Linux / Unix ein Prozess stirbt / endet und alle Informationen aus dem Prozess aus dem Systemspeicher entfernt werden, bleibt nur der Prozessdeskriptor erhalten. Der Prozess wird in den Zustand Z (Zombie) versetzt. Sein übergeordneter Prozess erhält ein Signal vom Kernel: SIGCHLDDies bedeutet, dass einer seiner untergeordneten Prozesse beendet wird, unterbrochen wird oder nach einer Unterbrechung fortgesetzt wird (in unserem Fall wird er einfach beendet).

Der übergeordnete Prozess muss jetzt den wait()Syscall ausführen, um den Beendigungsstatus und andere Informationen aus seinem untergeordneten Prozess zu lesen. Dann wird der Deskriptor aus dem Speicher entfernt und der Prozess ist kein Zombie mehr.

Wenn der übergeordnete Prozess den wait()Syscall nie aufruft , bleibt der Zombie-Prozessdeskriptor im Speicher und frisst den Verstand. Normalerweise sehen Sie keine Zombie-Prozesse, da der oben beschriebene Vorgang weniger Zeit in Anspruch nimmt.

Die Morgendämmerung der Toten

Jeder Prozessdeskriptor benötigt sehr wenig Speicher, sodass einige Zombies nicht sehr gefährlich sind (wie im echten Leben). Ein Problem ist, dass jeder Zombie-Prozess seine Prozess-ID behält und ein Linux / Unix-Betriebssystem eine begrenzte Anzahl von Pids hat. Wenn eine falsch programmierte Software viele Zombie-Prozesse generiert, kann es vorkommen, dass Prozesse nicht mehr gestartet werden können, da keine Prozess-IDs mehr verfügbar sind.

Also, wenn sie in großen Gruppen sind, sind sie sehr gefährlich (wie in vielen Filmen wird sehr gut demonstriert)

Wie können wir uns gegen eine Horde Zombies verteidigen?

Ein Schuss in den Kopf würde funktionieren, aber ich kenne den Befehl dafür nicht (SIGKILL wird nicht funktionieren, weil der Prozess bereits tot ist).

Nun, Sie können SIGCHLD über kill an den übergeordneten Prozess senden, aber wenn dieses Signal ignoriert wird, was dann? Ihre einzige Möglichkeit ist, den übergeordneten Prozess zu beenden und den Zombie durch den Init-Prozess zu "adoptieren". Init ruft regelmäßig den wait()Syscall an, um seine Zombiekinder zu säubern.

In deinem Fall

In Ihrem Fall müssen Sie SIGCHLD an den crond-Prozess senden:

root@host:~# strace -p $(pgrep cron)
Process 1180 attached - interrupt to quit

Dann von einem anderen Terminal:

root@host:~$ kill -17 $(pgrep cron)

Die Ausgabe ist:

restart_syscall(<... resuming interrupted call ...>) = ? ERESTART_RESTARTBLOCK (To be restarted)
--- SIGCHLD (Child exited) @ 0 (0) ---
wait4(-1, 0x7fff51be39dc, WNOHANG, NULL) = -1 ECHILD (No child processes) <-- Here it happens
rt_sigreturn(0xffffffffffffffff)        = -1 EINTR (Interrupted system call)
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=1892, ...}) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {0x403170, [CHLD], SA_RESTORER|SA_RESTART, 0x7fd6a7e9d4a0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({42, 0}, ^C <unfinished ...>
Process 1180 detached

Sie sehen, dass der wait4()Syscall -1 ECHILD zurückgibt, was bedeutet, dass kein untergeordneter Prozess vorhanden ist. Die Schlussfolgerung lautet also: cron reagiert auf den SIGCHLD-Systemaufruf und sollte die Apokalypse nicht erzwingen.

Chaos
quelle
1
Was, keine Cricketschläger und LPs?
Alexios
-3

Wenn der übergeordnete Thread vor seinem untergeordneten Thread beendet wird, werden alle untergeordneten Threads zu Zombie-Prozessen.

Sandeep
quelle
7
Nicht wahr, sie werden nur repariert. Bei Zombie-Prozessen wurde Waitpid nicht aufgerufen.
Chris Down
Vielleicht sprach er über Eltern- und Kinderprozesse; Ein untergeordneter Prozess wird zu einer "Waise", wenn sein übergeordneter Prozess "stirbt".
Barun