Warum läuft mein Prozess nach dem Abmelden noch?

10

Nachdem sshich mich angemeldet habe , gebe ich diesen Befehl ein bash:

sleep 50000000000000 &

Dann habe ich kill -9den sleepübergeordneten Prozess des Prozesses (dh bash). Dann wird das Terminalfenster gleichzeitig getrennt.

Wenn ich mich erneut anmelde, stelle ich fest, dass der sleepProzess noch läuft.

Frage : Warum kann der sleepProzess überleben, wenn ich mich abmelde und das Terminal geschlossen ist? In meinen Augen wird alles außer Dämonen und nohupProgrammen beim Abmelden getötet. Wenn sleepich auf diese Weise überleben kann, bedeutet das, dass ich diese Methode anstelle des nohupBefehls verwenden kann?

Kater
quelle
3
&Der Prozess wird in den Hintergrund verschoben (wie bei einem Daemon) und läuft weiter, obwohl Sie abgemeldet sind.
Aizuddin Zali

Antworten:

6

Tl; dr:

Warum kann der sleepProzess überleben, wenn ich mich abmelde und das Terminal geschlossen ist? In meinen Augen wird alles außer Dämonen und nohupProgrammen beim Abmelden getötet. Wenn sleepich auf diese Weise überleben kann, bedeutet das, dass ich diese Methode anstelle des nohupBefehls verwenden kann?

Sofern für die von basherzeugte Instanz sshdie huponexitOption festgelegt ist, wird kein Prozess beim Beenden / Abmelden auf irgendeine Weise beendet. Wenn die huponexitOption festgelegt ist, ist die Verwendung kill -9in der Shell keine gute Alternative zur Verwendung nohupin den untergeordneten Prozessen der Shell. nohupAuf den untergeordneten Prozessen der Shell werden sie weiterhin vor SIGHUPs geschützt, die nicht von der Shell stammen, und selbst wenn dies nicht wichtig nohupist , ist dies immer noch zu bevorzugen, da die Shell ordnungsgemäß beendet werden kann.


In bashgibt es eine Option namens huponexit, die, wenn gesetzt, bashSIGHUP seine Kinder beim Beenden / Abmelden macht;

In interaktiven Instanzen ohne Anmeldung bash , z. B. in einer von basherzeugten Instanz gnome-terminal, wird diese Option ignoriert. ob huponexitgesetzt oder nicht gesetzt, werden bashdie Kinder bashbeim Verlassen niemals von SIGHUPped ;

In interaktiven Anmeldeinstanzen bash , z. B. in einer von basherzeugten Instanz ssh, wird diese Option nicht ignoriert (sie ist jedoch standardmäßig deaktiviert). Wenn huponexitfestgelegt, bashwerden die untergeordneten Elemente bashbeim Beenden / Abmelden von SIGHUPped . Wenn dies nicht festgelegt huponexitist, werden bashdie Kinder bashbeim Beenden / Abmelden nicht von SIGHUPped .

Im Allgemeinen wird das Beenden / Abmelden von einer interaktiven Anmeldeinstanz bash, sofern die huponexitOption nicht aktiviert ist, die Shell nicht zu ihren untergeordneten SIGHUP machen, und das Beenden / Abmelden von einer interaktiven bashInstanz ohne Anmeldung macht die Shell nicht zu ihren untergeordneten SIGHUP ungeachtet;

Dies ist jedoch irrelevant in diesem Fall: mit kill -9 sleepunabhängig überleben, weil seinen Eltern - Prozess zu töten ( bash) keine Chance läßt letztere tun alles , um die alten (also beispielsweise , wenn die aktuelle bashInstanz ist eine Login - bashInstanz und die huponexitOption wurde gesetzt, um es zu registrieren).

Im Gegensatz zu anderen Signalen (wie einem SIGHUP-Signal, an das gesendet wird bash) wird ein SIGKILL-Signal niemals an die untergeordneten Prozesse eines Prozesses weitergegeben und daher sleepnicht einmal getötet.

nohupstartet einen Prozess, der gegen SIGHUP-Signale immun ist, was etwas anderes ist; Dadurch wird verhindert, dass der Prozess beim Empfang eines SIGHUP-Signals hängen bleibt, das in diesem Fall von der interaktiven Anmeldeinstanz empfangen werden kann, bashfalls die huponexitOption festgelegt und die Shell beendet wurde. Wenn Sie also technisch gesehen nohupeinen Prozess in einer interaktiven Anmeldeinstanz bashmit der huponexitOption "Nicht gesetzt" starten, wird verhindert, dass der Prozess beim Empfang eines SIGHUP-Signals hängen bleibt. Wenn Sie die Shell jedoch verlassen / abmelden, wird sie unabhängig davon nicht SIGHUP.

Im Allgemeinen gibt es jedoch nohupkeinen Grund, die kill -9On-Parent-Methode der nohupOn-Child-Methode vorzuziehen , wenn dies erforderlich ist, um zu verhindern, dass SIGHUP-Signale von der übergeordneten Shell kommen . stattdessen sollte es das Gegenteil sein.

Das Töten des Elternteils mit der kill -9Methode lässt dem Elternteil keine Möglichkeit nohup, ordnungsgemäß zu beenden , während das Starten des Kindes mit der Methode es dem Elternteil ermöglicht, durch andere Signale wie SIGHUP beendet zu werden (um ein Beispiel zu erstellen, das im Kontext sinnvoll ist eines Kindes begann zu verwenden nohup), die es ermöglichen, anmutig zu beenden.

kos
quelle
Mit anderen Worten, wenn ich ein Skript habe, das im Hintergrund platziert wurde, wird es auch dann noch ausgeführt, wenn ich den übergeordneten Prozess abbreche, z. B. meine Shell, oder? Was wäre ein Weg, um dieses Skript zu töten?
Sergiy Kolodyazhnyy
@Serg Wenn Sie die PID haben, beenden Sie einfach die PID. Wenn Sie die PID nicht gespeichert haben, aber den Prozess anhand seines Namens identifizieren können, ps -e | grep processsollten Sie die Prozesse zusammen mit der PID pgrep -x processauflisten (oder besser, wenn Sie sicher sind, dass Sie diesem einzelnen Prozess und nicht den nicht zugewiesenen Dingen entsprechen). Das Problem ist, dass, wenn Sie einen Prozess beenden, kill -9dessen Kinder im Besitz von sind upstart, daher ihre ursprüngliche PPID verloren geht und ihre PPID sich in die PID des Emporkömmlings ändert, wodurch sie nicht wiederzuerkennen sind (AFAIK), aber für ihren Namen oder ihre PID
kos
@kos Unter welchen Bedingungen nohupkann nicht verhindert werden, dass ein Prozess beim Empfang eines SIGHUP-Signals vom übergeordneten Prozess auflegt ? Ich versuche, einen Prozess im Hintergrund (in einem PuTTY SSH-Shell-Terminal) von auszuführen nohup <command> <arg> &. Wenn ich mich durch Klicken auf die XSchaltfläche PuTTY abmelde, wird der Hintergrundprozess sofort beendet. Wenn ich mich durch Eingabe exitdes PuTTY SSH-Shell-Terminals abmelde, wird der Prozess im Hintergrund fortgesetzt.
Userpal
3

bashStandardmäßig wird das HUP-Signal beim Beenden nicht an untergeordnete Prozesse gesendet . Genauer gesagt (danke @kos), es funktioniert nie für Nicht-Login-Shells .

Sie können bash so konfigurieren, dass es für Login-Shells ausgeführt wird, wenn Sie die Option festlegen huponexit. Führen Sie in einem Terminal Folgendes aus:

[romano:~] % bash -l

(dies startet eine neue "Login" Shell)

romano@pern:~$ shopt -s huponexit
romano@pern:~$ sleep 1234 &
[1] 32202
romano@pern:~$ exit
logout

Überprüfen Sie nun den sleepVorgang:

[romano:~] % ps augx | grep sleep
romano   32231  0.0  0.0  16000  2408 pts/11   S+   15:23   0:00 grep sleep

... läuft nicht: Es hat das HUP-Signal empfangen und wie angefordert beendet.

Rmano
quelle
@kos --- ja, du hast recht aber ... warum also wenn ich sleep 1000 & ; exitdas sleepüberlebe? Beachten Sie, dass wenn ich kill -HUPden sleepProzess, wird es beendet . Und selbst wenn huponexitgesetzt, sleepüberlebt der. Verwirrt ... (Ich werde versuchen, die Antwort besser zu verstehen und zu ändern, sonst werde ich sie löschen).
Rmano
2

Wenn sleepkann auf diese Weise überleben, wenn es bedeutet, dass ich diese Methode anstelle des nohupBefehls verwenden kann?

kill -9ist wirklich nicht der Weg, den man gehen sollte. Es ist, als würde man mit einer Waffe auf den Fernseher schießen, um ihn auszuschalten. Neben der komödiantischen Komponente gibt es keinen Vorteil. Prozesse können nicht abfangen oder ignorieren SIGKILL. Wenn Sie dem Prozess keine Chance geben, seine Arbeit zu beenden und zu bereinigen, bleiben möglicherweise beschädigte Dateien (oder ein anderer Status) in der Nähe und können nicht erneut gestartet werden. kill -9ist die letzte Hoffnung, wenn nichts anderes funktioniert.


Warum der Schlafprozess überleben kann, wenn ich mich abmelde und das Terminal geschlossen ist. In meinen Augen wird alles außer Daemon und Nohup-Programm beim Abmelden beendet.

Was passiert in Ihrem Fall:

Der übergeordnete Prozess von sleepist die aktuell ausgeführte bashShell. Wenn Sie kill -9diesen Bash ausführen, hat der Bash-Prozess nicht die Möglichkeit, einen SIGHUPan einen seiner untergeordneten Prozesse zu senden , da SIGKILL(der von gesendet wird kill -9) vom Prozess nicht erfasst werden kann. Der Schlafprozess läuft weiter. Schlaf wurde jetzt ein verwaister Prozess .

Der Init (PID 1) -Prozess führt einen Mechanismus aus, der als Reparenting bezeichnet wird. Das bedeutet, dass der Init-Prozess jetzt das übergeordnete Element dieses verwaisten Prozesses wird. init ist eine Ausnahme. Prozesse können untergeordnet werden, da Prozesse erfasst werden, die ihren ursprünglichen übergeordneten Prozess verloren haben. Übrigens: Ein Daemon (wie sshd) macht das, wenn er "in den Hintergrund geht".

Wenn dies nicht passieren würde, würde der verwaiste Prozess später (wenn er abgeschlossen ist) zu einem Zombie-Prozess. Dies ist, was passiert, wenn waitpid()es nicht aufgerufen wird (eine Verantwortung des übergeordneten Prozesses, die nicht erfüllt werden kann, wenn dieser Prozess beendet wurde). init ruft waitpid()in einem bestimmten Intervall auf, um Zombiekinder zu vermeiden.

Chaos
quelle
Der Prozess überlebt auch mit höflichen Signalen wie TERModerHUP
heemayl
@heemayl HUP hängt von der Shells-Konfiguration ab : huponext. Und TERM wird warten, bis der Schlaf beendet ist. Im Falle des Schlafbefehls der OP wären es Tausende von Jahren =)
Chaos
1

Das &startet den Prozess im Hintergrund. Wenn Sie eingeben ps -ef, sehen Sie, dass die übergeordnete Prozess-ID (PPID) Ihres Schlafes Ihre Bash ist. Dann abmelden und erneut anmelden. Der Prozess läuft nach dem Abmelden weiter. Nachdem Sie sich zum zweiten Mal angemeldet haben, ps -efwerden Sie erneut ausgeführt. Sie werden sehen, dass jetzt das übergeordnete Element Ihres Schlafprozesses mit der ID "1" verarbeitet wird. Das ist init, das übergeordnete Element aller Prozesse.

niemand
quelle
0

Wenn Sie verwenden, &wird das Programm als Hintergrund ausgeführt. Um das Programm im Hintergrund zu sehen, verwenden Sie den bgBefehl, und um es wieder als Vordergrund auszuführen, führen Sie es aus fg.

Ja, es gibt viele Möglichkeiten, das Programm am Laufen zu halten, selbst wenn das Hauptterminal beendet ist.

Aizuddin Zali
quelle
Vielen Dank. Die Manpage von Bash ist etwas verwirrend. Es hieß: "Vor dem Beenden sendet eine interaktive Shell das SIGHUP erneut an alle laufenden oder angehaltenen Jobs." ABER tatsächlich sendet die Shell SIGHUP nur an die Forground- Jobs. Die Hintergrundprozesse haben keine Chance, das SIGHUP-Signal zu empfangen (es sei denn, Sie ändern die Shell-Optionen 'huponexit')
tom_cat
@kos vielleicht hast du recht Ich ziehe die obige Schlussfolgerung aus diesem Beitrag: stackoverflow.com/questions/4298741/… jetzt bin ich verwirrter.
Tom_cat
@tom_cat Zurück zu dieser wieder, darüber nachzudenken , es zweimal: es gibt einfach keinen Fall , in dem die Schale kann verlassen mit einem Vordergrundprozess ausgeführt wird , kann es SIGHUPped oder etwas sein, aber das ist nicht verläßt . Das ist also richtig, es gilt nur für Hintergrundprozesse, da das Gegenteil keinen Sinn ergeben würde. Beachten Sie jedoch aus weiteren Untersuchungen, dass dies huponexitnur bei Login-Shells funktioniert, z. B. bei einer Shell, die über ssh(und nicht beispielsweise bei einer Shell, die über gnome-terminal) erhalten wurde
kos