Ich habe ein Bash-Skript, das ein Python3-Skript startet (nennen wir es startup.sh
), mit der folgenden Schlüsselzeile:
nohup python3 -u <script> &
Wenn ich ssh
direkt in dieses Skript einsteige und es aufrufe, läuft das Python-Skript nach dem Beenden im Hintergrund weiter. Wenn ich dies jedoch ausführe:
ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "./startup.sh"
Der Vorgang endet, sobald ssh
die Ausführung beendet ist und die Sitzung geschlossen wurde.
Was ist der Unterschied zwischen den beiden?
BEARBEITEN: Das Python-Skript führt einen Webdienst über Bottle aus.
EDIT2: Ich habe auch versucht , ein Init-Skript zu erstellen , das aufruft startup.sh
und ausgeführt wird ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "sudo service start <servicename>"
, aber das gleiche Verhalten hat.
EDIT3: Vielleicht ist es etwas anderes im Skript. Hier ist der Großteil des Skripts:
chmod 700 ${key_loc}
echo "INFO: Syncing files."
rsync -azP -e "ssh -i ${key_loc} -o StrictHostKeyChecking=no" ${source_client_loc} ${remote_user}@${remote_hostname}:${destination_client_loc}
echo "INFO: Running startup script."
ssh -i ${key_loc} -o StrictHostKeyChecking=no ${remote_user}@${remote_hostname} "cd ${destination_client_loc}; chmod u+x ${ctl_script}; ./${ctl_script} restart"
EDIT4: Wenn ich die letzte Zeile mit einem Schlaf am Ende laufen lasse:
ssh -i ${key_loc} -o StrictHostKeyChecking=no ${remote_user}@${remote_hostname} "cd ${destination_client_loc}; chmod u+x ${ctl_script}; ./${ctl_script} restart; sleep 1"
echo "Finished"
Es erreicht nie echo "Finished"
, und ich sehe die Flaschen-Server-Nachricht, die ich noch nie gesehen habe:
Bottle vx.x.x server starting up (using WSGIRefServer())...
Listening on <URL>
Hit Ctrl-C to quit.
Ich sehe "Fertig", wenn ich manuell SSH einsetze und den Vorgang selbst beende.
EDIT5: Wenn ich mit EDIT4 eine Anfrage an einen Endpunkt stelle, erhalte ich eine Seite zurück, aber die Flasche zeigt Fehler an:
Bottle vx.x.x server starting up (using WSGIRefServer())...
Listening on <URL>
Hit Ctrl-C to quit.
----------------------------------------
Exception happened during processing of request from ('<IP>', 55104)
quelle
strace
Linux odertruss
unter Solaris auszuführen und zu sehen, wie / warum es beendet wird. Wie zum Beispielssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> strace -fo /tmp/debug ./startup.sh
.&
Skript am Ende des Startvorgangs zu verwenden? Durch Hinzufügen von&
wird die Abhängigkeit Ihrer ssh-Sitzung von der übergeordneten ID aufgehoben (wenn übergeordnete IDs sterben, werden auch deren untergeordnete IDs gelöscht). Ich denke auch, dass dies eine doppelte Frage ist, die auf diesem vorherigen Beitrag basiert . Der Beitrag, den ich Ihnen im vorherigen Satz übermittelt habe, ist ein Duplikat dieses Beitrags, das möglicherweise detailliertere Informationen enthält.nohup ./startup.sh &
, aber es hatte das gleiche Verhalten.startup.sh
Enthält bereits eine Gabel (nohup python3 -u <script> &
), daher bin ich mir ziemlich sicher, dass ich nicht noch einmal gabeln muss.Antworten:
Ich würde den Befehl von seiner Standard-Ein- / Ausgabe trennen und Fehlerflüsse:
ssh
benötigt einen Indikator, der keine Ausgabe mehr hat und der keine Eingabe mehr benötigt. Etwas anderes als die Eingabe zu haben und die Ausgabeeinrichtung umzuleiten,ssh
kann sicher beendet werden, da die Eingabe / Ausgabe nicht vom Terminal kommt oder zum Terminal geht. Dies bedeutet, dass die Eingabe von einer anderen Stelle stammen muss und die Ausgabe (sowohl STDOUT als auch STDERR) an eine andere Stelle gehen sollte.Das
</dev/null
Teil wird/dev/null
als Eingabe für angegeben<script>
. Warum ist das hier sinnvoll:Alternativ sollte das Umleiten von einer anderen Eingabequelle relativ sicher sein, solange die aktuelle
ssh
Sitzung nicht geöffnet bleiben muss.Mit dem
>/dev/null
Teil leitet die Shell die Standardausgabe nach / dev / null um und verwirft sie im Wesentlichen.>/path/to/file
wird auch funktionieren.Der letzte Teil
2>&1
leitet STDERR zu STDOUT um.quelle
nohup python3 -u <script> >/dev/null 2>&1 &
undnohup python3 -u <script> > nohup.out 2>&1 &
arbeitete. Ich dachte, nohup leitet die gesamte Ausgabe automatisch um - was ist der Unterschied?nohup
hast du auf deinem Remote-Host? Ein POSIXnohup
ist nicht erforderlich, um umzuleitenstdin
, was ich verpasst habe, aber es sollte trotzdem umleitenstdout
undstderr
.nohup (GNU coreutils) 8.21
.nohup
werden Nachrichten gedruckt, wie znohup: ignoring input and appending output to ‘nohup.out’
.Schau dir an
man ssh
:Wenn Sie ausführen, führen
ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> "./startup.sh"
Sie das Shell-Skript startup.sh als ssh-Befehl aus.Aus der Beschreibung:
Auf dieser Grundlage sollte das Skript remote ausgeführt werden.
Der Unterschied zwischen diesem und dem Ausführen
nohup python3 -u <script> &
in Ihrem lokalen Terminal besteht darin, dass dies als lokaler Hintergrundprozess ausgeführt wird, während der Befehl ssh versucht, ihn als entfernten Hintergrundprozess auszuführen.Wenn Sie das Skript lokal ausführen möchten, führen Sie startup.sh nicht als Teil des Befehls ssh aus. Sie könnten so etwas versuchen
ssh -i <keyfile> -o StrictHostKeyChecking=no <user>@<hostname> && "./startup.sh"
Wenn Sie beabsichtigen, das Skript remote auszuführen und dieser Prozess fortgesetzt werden soll, nachdem Ihre SSH-Sitzung beendet wurde, müssen Sie zuerst eine
screen
Sitzung auf dem Remote-Host starten . Dann müssen Sie das Python-Skript auf dem Bildschirm ausführen, und es wird weiterhin ausgeführt, nachdem Sie Ihre SSH-Sitzung beendet haben.Siehe Bildschirm-Benutzerhandbuch
Obwohl ich denke, dass Bildschirm die beste Option ist, sollten Sie die Einstellung
shopt -s huponexit
auf dem Remote-Host in Betracht ziehen, bevor Sie den Befehl nohup ausführen, wenn Sie nohup verwenden müssen . Alternativ können Siedisown -h [jobID]
den Prozess mit markieren, damit SIGHUP nicht an ihn gesendet wird. 1Sehen Sie sich auch diese Zusammenfassung an, wie es
huponexit
funktioniert, wenn eine Shell beendet, getötet oder fallengelassen wird. Ich vermute, dass Ihr aktuelles Problem damit zusammenhängt, wie die Shell-Sitzung endet. 2Abschließend einige Beispiele zur Verwendung von shopt huponexit. 3
quelle
bash
Manpagehuponexit
sollte sich dies nur auf interaktive Shells und nicht auf Skripte auswirken - 'Wenn die Shell-Option huponexit mit shopt gesetzt wurde, sendet bash beim Beenden einer interaktiven Login-Shell ein SIGHUP an alle Jobs.'Vielleicht lohnt es sich, eine
-n
Option zu versuchen, wenn Sie eine startenssh
? Dadurch wird die Abhängigkeit von Remote-Prozessen von einem lokalen Prozess verhindertstdin
, der natürlich sofort nach demssh session
Ende geschlossen wird. Und dies führt zu einer Kündigung der Remote-Preise, wenn versucht wird, auf seine zuzugreifenstdin
.quelle
Ich vermute, Sie haben einen Rennzustand. Es würde ungefähr so aussehen:
Wenn ssh die Dinge nicht gekürzt hätte, wäre Folgendes passiert (über die Reihenfolge dieser beiden nicht sicher):
Die letzten beiden kritischen Schritte finden also nicht statt, da startup.sh und ssh beendet werden, bevor nohup Zeit hat, seine Sache zu erledigen.
Ich gehe davon aus, dass Ihr Problem verschwindet, wenn Sie am Ende von startup.sh einige Sekunden in den Ruhezustand versetzen. Ich weiß nicht genau, wie viel Zeit Sie brauchen. Wenn es wichtig ist, es auf ein Minimum zu beschränken, können Sie sich vielleicht etwas in proc ansehen, um zu sehen, wann es sicher ist.
quelle
/proc/$!/comm
nichtnohup
oder eher portabel istps -o comm= $!
.Dies klingt eher nach einem Problem mit dem, was das
python
Skript oderpython
selbst tut. Alles, wasnohup
wirklich funktioniert (Umleitungen vereinfachen), ist, den Handler für dasHUP
Signal aufSIG_IGN
(Ignorieren) zu setzen, bevor das Programm ausgeführt wird. Es gibt nichts, was das Programm daran hindern könnte, es zurückzusetzenSIG_DFL
oder einen eigenen Handler zu installieren, sobald es gestartet wird .Möglicherweise möchten Sie Ihren Befehl in Klammern setzen, damit Sie einen doppelten Verzweigungseffekt erhalten und Ihr
python
Skript nicht länger ein untergeordnetes Element des Shell-Prozesses ist. Z.B:Eine andere Sache, die auch einen Versuch wert sein kann (wenn Sie
bash
und nicht eine andere Shell verwenden), ist, dasdisown
eingebaute anstelle zu verwendennohup
. Wenn alles so funktioniert, wie es dokumentiert ist, sollte dies eigentlich keinen Unterschied machen. In einer interaktiven Shell würde dies jedoch verhindern, dass sich dasHUP
Signal auf Ihrpython
Skript ausbreitet . Sie können die Ablehnung in der nächsten Zeile oder in der gleichen Zeile wie unten hinzufügen (beachten Sie, dass das Hinzufügen von a;
nach a&
ein Fehler in istbash
):Wenn das oben Genannte oder eine Kombination davon nicht funktioniert, ist der einzige Ort, an dem das Problem behoben werden kann, sicherlich das
python
Skript selbst.quelle
huponexit
Zeug meinen, sollte das Ausführen in einer Subshell den gleichen Effekt haben,disown
da der Prozess nicht zur Jobliste hinzugefügt wird.disown
. Erwarten Sie jedoch nicht, dass es viel bewirken wird. Am besten ändern Sie daspython
Skript so, dass Sie wissen, warum es beendet wird.nohup
ist.Ich denke, es liegt daran, dass der Job an die Sitzung gebunden ist. Sobald dies beendet ist, werden auch alle Benutzeraufträge beendet.
quelle
Wenn Sie
nohup
die Ausgabedatei öffnen können, haben Sie möglicherweise einen Hinweis daraufnohup.out
. Es ist möglich, dass Siepython
sich nicht im Pfad befinden, wenn Sie das Skript über ausführenssh
.Ich würde versuchen, eine Protokolldatei für den Befehl zu erstellen. Versuchen Sie es mit:
quelle
ssh
, um das Skript manuell auszuführen, also gehe ich davon aus, dass sich Python3 im Pfad befindet.