Warum wartet SSH nicht auf Hintergrundprozesse?

13

Warum ssh -twartet es nicht darauf, dass Hintergrundjobs beendet werden?

Beispiel:

ssh user@example 'sleep 2 &'

Dies funktioniert wie erwartet, da ssh nach 2 Sekunden zurückkehrt, wohingegen

ssh user@example -t 'sleep 2 &'

wartet nicht sleepbis zum Ende und kehrt sofort zurück.

Kann jemand den Grund dafür erklären? Gibt es eine Möglichkeit zu ssh -twarten, bis alle Hintergrundprozesse abgeschlossen sind, bevor Sie zurückkehren?

Mein Anwendungsfall ist, dass ich ein Skript mit ssh -tstarte und dieses Skript mehrere Hintergrundjobs startet, die nach Beendigung des Hauptskripts am Leben bleiben sollten. Damit ssh -tist das bisher nicht möglich.

Philipp Murry
quelle

Antworten:

22

Without -t, sshdruft die Standardausgabe der Remote-Shell (und der untergeordneten Elemente like sleep) und stderr über zwei Pipes ab (und sendet die Eingaben des Clients auch über eine andere Pipe).

sshd Wartet auf den Prozess, in dem die Anmeldeshell des Benutzers gestartet wurde. Nach Abschluss dieses Prozesses wird jedoch auf eof auf der stdout-Pipe gewartet (nicht auf die stderr-Pipe, zumindest im Fall von openssh).

Und eof tritt auf, wenn auf der schreibenden Seite der Pipe kein Dateideskriptor für einen Prozess geöffnet ist, was normalerweise nur dann der Fall ist, wenn alle Prozesse, deren stdout nicht auf etwas anderes umgeleitet wurde, nicht mehr ausgeführt werden.

Wenn Sie verwenden -t, werden sshdkeine Rohre verwendet. Stattdessen erfolgt die gesamte Interaktion (stdin, stdout, stderr) mit der Remote-Shell und ihren untergeordneten Objekten über ein Pseudo-Terminal-Paar.

Bei einem Pseudo-Terminal-Paar gibt es für die sshdInteraktion mit der Masterseite keine vergleichbare EOF-Behandlung und keine Möglichkeit, festzustellen, ob auf der Slave-Seite des Pseudo-Terminals noch Prozesse mit offenen FDS vorhanden sind, sodass nur auf die Beendigung von gewartet wird Der Prozess, in dem die Anmeldeshell des Remotebenutzers ausgeführt und dann beendet wird.

Bei diesem Ausgang wird die Masterseite des Pty-Paars geschlossen, was bedeutet, dass das Pty zerstört wird, sodass vom Slave gesteuerte Prozesse ein SIGHUP erhalten (was sie standardmäßig beenden würde).

Stéphane Chazelas
quelle
1
danke für die gründliche antwort! eine andere Sache, die ich wissen möchte: Beenden alle Hintergrundprozesse, sobald das Pseudoterminal beendet ist? Das Skript, das ich starte, startet einen Dienst, der mit ssh gut funktioniert. Bei Verwendung von ssh -t wird der Dienst jedoch nicht gestartet. es scheint, dass der Dienst beendet wird, sobald ssh zurückkommt.
Philipp Murry
Tatsächlich gibt es eine Möglichkeit für die Masterseite eines Pseudoterminals zu wissen, wann alle Slave-Dateideskriptoren geschlossen wurden. Es ist derselbe Mechanismus, der von einem echten Terminal ausgelöst wird, wenn alle Dateideskriptoren für dieses Terminal tatsächlich geschlossen wurden.
JdeBP
@JdeBP, würdest du gerne expandieren? Ich bin mir nicht sicher was du meinst. AFAICT-Terminalemulatoren (mindestens xterm und gnome-terminal) kümmern sich nicht um Prozesse, bei denen fds noch für den Slave geöffnet ist, als der Prozess ausgeführt wurde, in dem sie die Shell ausgeführt haben
Stéphane Chazelas
@PhilippMurry Mit können Sie nohupein Skript so laufen lassen. (Sie könnten auch in Betracht ziehen, lang laufende Jobs innerhalb von zu starten, tmuxdamit Sie deren Fortschritt interaktiv überwachen können, aber eine Protokolldatei funktioniert
einwandfrei
5

Verwendung wait:

ssh user@example -t 'sleep 2 & wait'
Ipor Sircer
quelle