Was genau bestimmt, ob ein Job im Hintergrund beendet wird, wenn die Shell beendet oder beendet wird?

12

Diese Frage hat kommen ganz eine Menge ( wirklich viel ), aber ich finde die Antworten im Allgemeinen unvollständig. Die allgemeine Frage lautet: "Warum wird / wird mein Job nicht getötet, wenn ich ssh verlasse / töte?", Und hier ist, was ich gefunden habe. Die erste Frage lautet: Wie allgemein sind die folgenden Informationen? Das Folgende scheint für das moderne Debian-Linux zu gelten, aber mir fehlen einige Teile. und was müssen andere wissen?

  1. Alle untergeordneten Prozesse einer Shell, die über eine SSH-Verbindung geöffnet wurde oder nicht, werden mit SIGHUP beendet, wenn die SSH-Verbindung nur geschlossen wird , wenn die huponexitOption gesetzt ist: Ausführen, shopt huponexitum festzustellen, ob dies der Fall ist.

  2. Wenn dies huponexitzutrifft, können Sie den Prozess verwenden nohupoder disownvon der Shell trennen, damit er beim Beenden nicht beendet wird. Oder führen Sie Dinge mit screen.

  3. Wenn huponexitfalsch ist, was der Standard ist auf zumindest einige in diesen Tagen Linuxe, dann backgrounded Arbeitsplätze nicht auf normalen Abmelde getötet werden.

  4. Aber selbst wenn huponexitfalsch ist, dann , wenn die SSH - Verbindung wird getötet , oder Tropfen (anders als normal Logout), dann backgrounded Prozesse werden noch getötet werden. Dies kann durch disownoder nohupwie in (2) vermieden werden .

  5. Es gibt einen gewissen Unterschied zwischen (a) Prozessen, deren übergeordneter Prozess das Terminal ist, und (b) Prozessen, bei denen stdin, stdout oder stderr mit dem Terminal verbunden sind . Ich weiß nicht, was mit Prozessen passiert, die (a) und nicht (b) sind oder umgekehrt.

Letzte Frage: Wie kann ich Verhalten vermeiden (3)? Mit anderen Worten, standardmäßig werden in Debian-Hintergrundprozessen nach dem Abmelden fröhlich von selbst ausgeführt, jedoch nicht, nachdem die SSH-Verbindung unterbrochen wurde. Ich möchte, dass bei Prozessen dasselbe passiert, unabhängig davon, ob die Verbindung normal geschlossen oder unterbrochen wurde. Oder ist das eine schlechte Idee?

Bearbeiten: Eine andere, wichtige Möglichkeit, um zu verhindern, dass Jobs getötet werden, die in beiden Fällen funktioniert (?), Besteht darin, sie über den Bildschirm auszuführen . Bei der Frage geht es jedoch mehr darum zu verstehen, wann Dinge getötet werden und wann nicht: Manchmal möchten die Leute, dass die Jobs zum Beispiel beim Abmelden getötet werden.

Weitere Themen : - Erläuterung zu Signalen (Seufzen), Jobs und dem steuernden Terminal - /server/117152/do-background-processes-get-a-sighup-when-logging-off - SSH fortsetzen Hintergrundaufgabe / Jobs beim Schließen von SSH - Wird ein im Hintergrund platzierter Job nach dem Schließen einer SSH-Sitzung weiter ausgeführt? - Verhindern, dass ein bereits laufender Hintergrundprozess nach dem Schließen des SSH-Clients gestoppt wird. - Wie kann ich einen Prozess über SSH starten, damit er nach dem Trennen der Verbindung weiter ausgeführt wird? - Remote-Job kann unter OS X nicht ausgeführt werden. - SSH-Verbindung schließen

Petrelharp
quelle

Antworten:

1

Ein Prozess wird nicht "mit SIGHUP getötet" - zumindest nicht im engeren Sinne des Wortes. Wenn die Verbindung getrennt wird, wird dem Steuerungsprozess des Terminals (in diesem Fall Bash) ein Auflegesignal * gesendet, das üblicherweise als "HUP-Signal" oder einfach "SIGHUP" abgekürzt wird.

Wenn ein Prozess ein Signal empfängt, kann er es nach Belieben verarbeiten **. Die Standardeinstellung für die meisten Signale (einschließlich HUP) ist das sofortige Beenden. Es steht dem Programm jedoch frei, das Signal stattdessen zu ignorieren oder sogar eine Art Signalhandlerfunktion auszuführen.

Bash wählt die letzte Option. Der HUP-Signalhandler prüft, ob die Option "huponexit" wahr ist, und sendet in diesem Fall SIGHUP an jeden seiner untergeordneten Prozesse. Erst wenn es damit fertig ist, wird Bash beendet.

Ebenso kann jeder untergeordnete Prozess tun, was er will, wenn er das Signal empfängt: Belassen Sie die Standardeinstellung (dh sterben Sie sofort), ignorieren Sie sie oder führen Sie einen Signalhandler aus.

Nohup ändert nur die Standardaktion für den untergeordneten Prozess in "Ignorieren". Sobald der untergeordnete Prozess ausgeführt wird, kann er seine eigene Antwort auf das Signal ändern.

Aus diesem Grund sterben einige Programme, obwohl Sie sie mit nohup ausgeführt haben:

  1. Nohup setzt die Standardaktion auf "ignorieren".
  2. Das Programm muss beim Beenden eine Art Bereinigung durchführen, daher installiert es einen SIGHUP-Handler, der im Übrigen das Flag "Ignorieren" überschreibt.
  3. Wenn das SIGHUP eintrifft, wird der Handler ausgeführt, bereinigt die Datendateien des Programms (oder was auch immer getan werden muss) und beendet das Programm.
  4. Der Benutzer kennt den Handler oder die Bereinigung nicht oder kümmert sich nicht darum und sieht nur, dass das Programm trotz nohup beendet wurde.

Hier kommt "disown" ins Spiel. Bei einem von Bash abgelehnten Prozess wird unabhängig von der Option huponexit niemals das HUP-Signal gesendet. Selbst wenn das Programm einen eigenen Signalhandler einrichtet, wird das Signal nie tatsächlich gesendet, sodass der Handler niemals ausgeführt wird. Beachten Sie jedoch, dass das Programm, wenn es versucht, einem abgemeldeten Benutzer Text anzuzeigen, einen E / A-Fehler verursacht, der dazu führen kann, dass das Programm trotzdem beendet wird.

* Und ja, bevor Sie fragen, bleibt die Terminologie "Auflegen" aus den Tagen des UNIX-DFÜ-Mainframes übrig.

** Die meisten Signale jedenfalls. SIGKILL zum Beispiel bewirkt immer, dass das Programm sofort beendet wird.

HiddenWindshield
quelle
2

Punkte 1-4 sind correct.I weiß nichts über Punkt 5. Was Ihren letzten Punkt, eine feine Anwendung, Bildschirm , ermöglicht es Ihnen , alle Prozesse laufen zu ihrem natürlichen Ende zu lassen, unabhängig davon , wie Sie die Verbindung beenden. Bildschirm ist in den Repos.

Die Beschreibung des Bildschirms durch den Mann ist nicht leicht zu lesen, heißt aber unter anderem:

Wenn screen aufgerufen wird, wird ein einzelnes Fenster mit einer Shell (oder dem angegebenen Befehl) erstellt und dann aus dem Weg geräumt, sodass Sie das Programm wie gewohnt verwenden können. Anschließend können Sie jederzeit neue (Vollbild-) Fenster mit anderen Programmen (einschließlich weiterer Shells) erstellen, vorhandene Fenster beenden, eine Liste von Fenstern anzeigen, die Ausgabeprotokollierung ein- und ausschalten sowie Text kopieren und einfügen Zeigen Sie zwischen den Fenstern den Scrollback-Verlauf an, wechseln Sie auf beliebige Weise zwischen den Fenstern usw. Alle Fenster führen ihre Programme völlig unabhängig voneinander aus. Programme werden weiterhin ausgeführt, wenn ihr Fenster derzeit nicht sichtbar ist und selbst wenn die gesamte Bildschirmsitzung vom Benutzerterminal getrennt ist. Wenn ein Programm beendet wird, beendet der Bildschirm (standardmäßig) das Fenster, in dem es enthalten ist. Wenn dieses Fenster im Vordergrund war, wechselt die Anzeige zum vorherigen Fenster. Wenn keine mehr übrig sind, wird der Bildschirm beendet.

Ich habe den wichtigsten Teil hervorgehoben: Sie können das Fenster mit dem Befehl Strg + a + d trennen, und dann können Sie Ihre Sitzung beenden / abmelden, und das jetzt getrennte Fenster bleibt weiterhin aktiv, während die darin enthaltenen Programme noch ausgeführt werden. Wenn Sie eine Verbindung herstellen, indem Sie beispielsweise eine neue SSH-Sitzung initiieren, setzt der Befehl screen -r die zuvor getrennte Bildschirmsitzung fort, wobei alle Ausgaben für Standardfehler / -ausgaben deutlich sichtbar sind.

MariusMatutiae
quelle