Frage

Ich habe einige Prozesse als angezeigt als <defunct> in top (und ps). Ich habe die Dinge aus den wirklichen Skripten und Programmen abgeholt.

In meinem crontab:

* * * * * /tmp/launcher.sh /tmp/tester.sh

Die Inhalte von launcher.sh (Das ist natürlich mit der ausführbaren Datei gekennzeichnet):

#!/bin/bash
# the real script does a little argument processing here
"$@"

Die Inhalte von tester.sh (Das ist natürlich mit der ausführbaren Datei gekennzeichnet):

#!/bin/bash
sleep 27 & # the real script launches a compiled C program in the background

ps zeigt Folgendes:

user       24257 24256  0 18:32 ?        00:00:00 [launcher.sh] <defunct>
user       24259     1  0 18:32 ?        00:00:00 sleep 27

Beachten Sie, dass tester.sh Es erscheint nicht-es ist nach dem Start des Hintergrundjobs verlassen.

Warum tut launcher.sh bleiben, markiert <defunct>? Es scheint dies nur zu tun, wenn es von gestartet wird cron-NICHT, wenn ich es selbst laufe.

Zusätzliche Anmerkung: launcher.sh ist ein gemeinsames Skript im System, auf dem das ausgeführt wird, das nicht leicht zu ändern ist. Die anderen Dinge (crontab, tester.sh, sogar das Programm, das ich anstelle von betreibe sleep) kann viel leichter verändert werden.

War es hilfreich?

Lösung

Weil sie nicht Gegenstand von a waren wait(2) Systemanruf.

Da jemand in Zukunft auf diese Prozesse wartet, kann der Kernel sie nicht vollständig loswerden oder es kann nicht in der Lage sein, das auszuführen wait Systemaufruf, weil er nicht mehr den Ausstiegsstatus oder den Beweis für seine Existenz mehr gibt.

Wenn Sie eine von der Shell aus starten, fängt Ihre Shell Sigchld ein und führt trotzdem verschiedene Waitvorgänge aus, sodass nichts lange nicht mehr nicht mehr in der Lage bleibt.

Aber Cron ist nicht in einem Wartezustand, es schläft, also kann das nicht mehr existierende Kind eine Weile in der Nähe bleiben, bis Cron aufwacht.


Aktualisieren: Antwort auf Kommentar ... hmm. Ich habe es geschafft, das Problem zu duplizieren:

 PPID   PID  PGID  SESS COMMAND
    1  3562  3562  3562 cron
 3562  1629  3562  3562  \_ cron
 1629  1636  1636  1636      \_ sh <defunct>
    1  1639  1636  1636 sleep

Also, was passiert ist, war, denke ich:

  • Cron Forks und Cron Child starten Shell
  • Shell (1636) beginnt SID und PGID 1636 und beginnt Schlaf
  • Shell Exits, Sigchld an Cron 3562 gesendet
  • Signal wird ignoriert oder misshandelt
  • Shell dreht Zombie. Beachten Sie, dass der Schlaf zu Init repariert ist. Wenn der Schlaf init das Signal erhält und aufräumt. Ich versuche immer noch herauszufinden, wann der Zombie erntet wird. Wahrscheinlich ohne aktive Kinder Cron 1629 findet heraus, dass es ausgehen kann. Zu diesem Zeitpunkt wird der Zombie repariert, um zu initieren und zu ernten. Jetzt wundern wir uns über die fehlende Sigchld, die Cron hätte verarbeiten sollen.
    • Es ist nicht unbedingt Vixie Crons Schuld. Wie Sie hier sehen können, Libdaemon installiert einen Sigchld -Handler während daemon_fork(), und dies könnte die Signalabgabe bei einem schnellen Ausgang von Intermediate 1629 beeinträchtigen

      Jetzt weiß ich nicht einmal, ob Vixie Cron auf meinem Ubuntu -System sogar mit Libdaemon gebaut ist, aber zumindest habe ich eine neue Theorie. :-)

Andere Tipps

Ich vermute, dass Cron auf alle Subprozesse in der Sitzung wartet. Siehe Warten Sie (2) in Bezug auf negative PID -Argumente. Sie können die Sitzung mit:

ps faxo stat,euid,ruid,tty,tpgid,sess,pgrp,ppid,pid,pcpu,comm

Folgendes sehe ich (bearbeitet):

STAT  EUID  RUID TT       TPGID  SESS  PGRP  PPID   PID %CPU COMMAND
Ss       0     0 ?           -1  3197  3197     1  3197  0.0 cron
S        0     0 ?           -1  3197  3197  3197 18825  0.0  \_ cron
Zs    1000  1000 ?           -1 18832 18832 18825 18832  0.0      \_ sh <defunct>
S     1000  1000 ?           -1 18832 18832     1 18836  0.0 sleep

Beachten Sie, dass der SH und der Schlaf in derselben Sitzung sind.

Verwenden Sie den Befehlssatz (1). Hier ist tester.sh:

#!/bin/bash
setsid sleep 27 # the real script launches a compiled C program in the background

Beachten Sie, dass Sie nicht brauchen &, SetSID stellt es in den Hintergrund.

Meiner Meinung nach wird es durch den Prozess des Prozesses (von Crond für jede Aufgabe hervorgebracht) verursacht, das auf Eingaben auf Stdin wartet, das in die Stdout/Stderr des Befehls im Crontab geleitet wird. Dies geschieht, weil Cron in der Lage ist, die resultierende Ausgabe per E -Mail an den Benutzer zu senden.

Daher wartet Crond auf EOF, bis der Benutzerbefehl und alles, was Kinderprozesse hervorgebracht haben, das Rohr geschlossen haben. Wenn dies erfolgt, fährt Crond mit der Wartedatement fort und dann verschwindet der nicht mehr existierende Benutzerbefehl.

Ich denke, Sie müssen jeden hervorgebrachten Subprozess in Ihrem Skript -Formular explizit trennen (zB, indem Sie sie in eine Datei oder /Dev /Null umleiten.

Die folgende Zeile sollte also in Crontab funktionieren:

* * * * * ( /tmp/launcher.sh /tmp/tester.sh &>/dev/null & ) 

Ich würde empfehlen, das Problem zu lösen, indem Sie einfach nicht zwei getrennte Prozesse haben: haben launcher.sh Tun Sie dies in seiner letzten Zeile:

exec "$@"

Dadurch wird der überflüssige Prozess beseitigt.

Ich fand diese Frage, als ich nach einer Lösung mit einem ähnlichen Problem suchte. Leider hat Antworten in dieser Frage mein Problem nicht gelöst.

Das Abtöten des nicht mehr existierenden Prozesses ist keine Option, da Sie seinen übergeordneten Prozess finden und abtöten müssen. Am Ende habe ich die nicht mehr existierenden Prozesse auf folgende Weise getötet:

ps -ef | grep '<defunct>' | grep -v grep | awk '{print "kill -9 ",$3}' | sh

In "Grep" '"können Sie die Suche auf einen bestimmten nicht mehr existierenden Prozess eingrenzen, nach dem Sie suchen.

Ich habe das gleiche Problem so oft getestet. Und schließlich habe ich die Lösung. Geben Sie einfach die '/bin/bash' vor dem unten gezeigten Bash -Skript an.

* * * * * /bin/bash /tmp/launcher.sh /tmp/tester.sh
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top