Verwenden von SSH zum Remote-Starten eines Prozesses

18

Ich habe ein Skript geschrieben, mit dem ich einen neuen Dienst auf mehrere von mir kontrollierte Maschinen pushe und verteile. Um den Prozess auszuführen, verwende ich ssh, um den Prozess remote zu starten. Leider scheint der SSH-Befehl immer dann, wenn ich SSH zum Starten des Prozesses verwende, nie zurückzukehren, was dazu führt, dass das Skript blockiert.

Der Befehl wird wie folgt angegeben: ssh $ user @ $ host "/ root / command &". Wenn ich einfache Befehle wie ps oder who ausführe, wird der SSH-Befehl sofort zurückgegeben. Wenn ich jedoch versuche, meinen Prozess zu starten, wird er nicht zurückgegeben. Ich habe versucht, meinen Prozess in ein einfaches Bash-Skript zu packen, das den Prozess startet und dann beendet. Dabei bleibt jedoch auch der SSH-Befehl hängen (auch wenn das Bash-Skript eine Erfolgsmeldung ausgibt und normal beendet wird).

Hat jemand einen Einblick, was dieses Verhalten verursacht und wie ich den SSH-Befehl zurückgeben kann, sobald der Prozess gestartet wurde?

Vielen Dank für Ihre Erkenntnisse!

rmrobins
quelle
Geben Sie die genaue Befehlszeile an, die Sie verwenden ... lassen Sie Passwörter / Benutzernamen / IPs weg
Joseph Kern
ssh $ SSH_USER @ $ HOST_ADDR "/ root / AppName &"
rmrobins
Ich sollte erwähnen, dass ich SSH-Schlüssel eingerichtet habe, sodass es nicht erforderlich ist, Kennwörter zu verwenden, um Befehle auf den Remote-Systemen auszuführen.
RMROBINS
@rmrobins, eine sehr gute schrittweise Einstellung der öffentlichen Schlüsselauthentifizierung.
Nik

Antworten:

28

SSH verbindet stdin, stdout und stderr der Remote-Shell mit Ihrem lokalen Terminal, sodass Sie mit dem Befehl interagieren können, der auf der Remote-Seite ausgeführt wird.

Als Nebeneffekt wird es so lange ausgeführt, bis diese Verbindungen geschlossen wurden. Dies geschieht nur, wenn der Remote-Befehl und alle seine untergeordneten Elemente (!) Beendet wurden (da die untergeordneten Elemente, mit denen "&" beginnt, std * von ihren erben) übergeordneter Prozess und lassen Sie ihn offen).

Also musst du sowas benutzen

ssh user@host "/script/to/run < /dev/null > /tmp/mylogfile 2>&1 &"

<,> Und 2> & 1 leiten stdin / stdout / stderr von Ihrem Terminal weg. Das "&" bewirkt dann, dass Ihr Skript in den Hintergrund tritt. In der Produktion würden Sie stdin / err natürlich in eine geeignete Logdatei umleiten.

Sehen

http://osdir.com/ml/network.openssh.general/2006-05/msg00017.html

Bearbeiten:

Habe gerade herausgefunden, dass das < /dev/nullobige nicht notwendig ist (aber das Umleiten von stdout / err ist ). Keine Ahnung warum ...

sleske
quelle
Danke, genau das habe ich gesucht - mir ist nicht eingefallen, dass der Prozess die std * erben würde, auch wenn & verwendet wird, um sie im Hintergrund zu starten.
RMROBINS
+1! Funktioniert bei mir. Und Sie können die Ausgabe auch drucken, indem Sie die Protokolldatei erneut ausgeben: ssh user@host "/script/to/run > /tmp/ssh.stdout 2>&1 && cat /tmp/ssh.stdout && rm -f /tmp/ssh.stdout"
Fishdrowned
5

Du könntest nohup versuchen . Man nohup für mehr Details.

ssh host "nohup script &"

Wenn Sie die Ausgabe auf dem Remote-Computer behalten möchten, finden Sie hier eine Variante .

ssh user@host 'export REMOTE=myname; nice nohup ./my-restart >
logfile.log 2>&1 &'
Jauder Ho
quelle
5

Eine andere Alternative wäre es, eine abgetrennte zu zünden screen(1), so etwas wie:

ssh -l user host "screen -d -m mycommand"

Dies startet einen getrennten Bildschirm (der die gesamte Interaktion in ihm aufzeichnet) und kehrt dann sofort zurück und beendet die ssh-Sitzung.

Mit etwas mehr Einfallsreichtum können Sie auf diese Weise recht komplexe Remote-Befehlsaufrufe lösen.

towo
quelle
4
 -f      Requests ssh to go to background just before command execution.
         This is useful if ssh is going to ask for passwords or
         passphrases, but the user wants it in the background.  This
         implies -n.  The recommended way to start X11 programs at a
         remote site is with something like ssh -f host xterm.

         If the ExitOnForwardFailure configuration option is set to “yes”,
         then a client started with -f will wait for all remote port for‐
         wards to be successfully established before placing itself in the
         background.
Teddy
quelle
1
Das Problem bei dieser Methode ist, dass der SSH-Befehl nicht tatsächlich beendet wird, sondern einfach im Hintergrund ausgeblendet wird, sodass der Host, auf dem das Skript ausgeführt wird, eine große Anzahl von SSH-Befehlen im Hintergrund hat, die niemals zurückkehren, da die SSH-Befehle niemals zurückkehren ( dh das Wurzelproblem, das ich lösen möchte)
rmrobins
-1

Ich denke der richtige Weg wäre

ssh user@host exec script.sh &
nik
quelle
Nein, das geht bei mir nicht. Warum sollte es
sleske
Ich habe den Hintergrund nicht über ssh gepusht, habe versucht, ohne einen Begriff zur Hand. mein Fehler.
Nik