Erläuterung
Es geht nicht darum wait
. Ich denke, das ist was passiert:
Sie verwenden <<
, so stdin
von ssh
bis zu einem gewissen Descriptor umgeleitet wird, durch die das gesamte hier Dokument fließt.
Diese andere Antwort erläutert, wie + ssh
erfasst werden kann, wenn verwendet wird. Darauf kommt es an:CtrlC-t
Auf der Clientseite
ssh
wird versucht, dentty
vonstdin
" used " in den "raw" -Modus zu setzen. […] Das Einstellen des Raw-Modus bedeutet, dass Zeichen, die normalerweise Signale (wie z. B. Ctrl+ C) senden würden, stattdessen einfach in den Eingabestrom eingefügt werden.
In Ihrem Fall ist es nicht dasselbe, das stdin
Ihre lokale Shell verwendet. tty
Die von Ihrer lokalen Shell verwendete Shell bleibt erhalten, sie ist niemals auf den "rohen" Modus eingestellt.
Wenn Sie also Ctrl+ Cdrücken, wirkt es lokal und wird beendet ssh
. In diesem Moment bekommt die entfernte Seite SIGHUP
. Deine trap
Arbeiten und tötet java
. Ich denke, es gibt hier eine Falle: a trap
führt einen bestimmten Code als Antwort auf ein gegebenes Signal aus, verhindert jedoch nicht, dass das Signal seine normale Wirkung hat. Daher scheint es mir, dass Sie java
auch ohne einen getötet werden würden, trap
weil es eine Aufgabe der Shell ist, die als Antwort beendet wird SIGHUP
.
Die Shell, die beendet wird, hört auf, ihre Shell zu lesen und zu interpretieren stdin
. Deshalb wird alles, was folgt, wait
verworfen.
Lösung
commands() { cat <<-'COMMANDS' cleanup() { # cleanup code here echo "Done. Logging out" sleep 2 logout } echo "Preparing execution" java -jar execute.jar & executePID=$! echo "Ready." echo "CTRL+C to clean and close" trap "kill $executePID; cleanup" INT HUP wait $executePID cleanup COMMANDS } stty raw -echo; cat <(commands) - | ssh -t $USER@remote.far; stty -raw echo
Die letzte Zeile ist der eigentliche Befehl. Zuerst bereiten wir tty
so Ctrl+ Cnicht lokal handeln kann. Dann verketten wir Befehle und Standardeingaben und übergeben sie an die Remote-Shell. Ich kann dies mit diesem Dokument nicht direkt tun, die command
Funktion ist eine Problemumgehung (es wäre einfacher, eine reguläre Datei zu verwenden, aber Sie sagten, Sie könnten nicht mehr als eine verwenden). Nach ssh
und cat
Beenden setzen wir den tty
Normalzustand.
Ein Pseudo-Terminal ist unerlässlich, stellen Sie also sicher, dass es ssh -t
funktioniert ( -tt
ggf. verwenden).
Die Remote-Shell muss alle Befehle lesen (zwischenspeichern) commands
, nur dann kann Ctrl+ sie erhalten, Cwenn Sie sie drücken. Ich denke, das bedeutet, dass Sie danach nicht zu viel Code haben können wait
. Was auch immer Sie danach tun möchten, SIGINT
muss von innen ausgeführt werden trap
. Dies ist der Grund, warum ich eine einzige cleanup
Funktion verwendet habe, die alles macht.
Der Code ist nicht narrensicher. Drücken Sie Ctrl+ Czu früh oder mehrmals und Sie befinden sich in der Remote-Shell oder mit etwas "defektem" Local tty
. In diesem Fall setzen Sie den Befehl reset
mit dem Befehl zurück tty
.
Sie müssen eine Taste drücken (z. B. Enter), wenn "Verbindung zu ... geschlossen" angezeigt wird. Der Grund ist cat
, dass die Pipe ssh
nicht mehr kaputt ist (weil sie nicht mehr vorhanden ist), bis versucht wird, etwas zu schreiben.
Alternative
Wenn die oben genannte Lösung aus irgendeinem Grund nicht für Sie funktioniert, verwenden Sie diese einfachere Alternative. Das hier Dokument ist genau wie zuvor. In diesem Fall machen wir nicht mit Zohan an tty
, Ctrl+ Cbeenden lokale ssh
wie es mit Ihrem ursprünglichen Code tut. Der Unterschied (in Bezug auf Ihren Code) ist trap
die Reinigung. Ich denke, es wäre genug, SIGHUP
nur eine Falle zu stellen .
ssh -t $USER@remote.far <<-'COMMANDS' cleanup() { # cleanup code here echo "Done. Logging out" sleep 2 logout } echo "Preparing execution" java -jar execute.jar & executePID=$! echo "Ready." echo "CTRL+C to clean and close" trap "kill $executePID; cleanup" INT HUP wait $executePID cleanup COMMANDS
Hinweis: Wenn der trap
Auslöser ausgelöst wird, wird cleanup
eine Nachricht angezeigt, die jedoch nicht angezeigt wird, da Ihre lokale Verbindung ssh
bereits getrennt ist. Sie werden die Nachricht nur sehen, wenn Sie java
ohne das Symbol beenden trap
. Ihr Bereinigungscode ( # cleanup code here
) sollte noch ausgeführt werden.