PuTTY-Remotebefehl mit While-Schleife

PuTTY-Remotebefehl mit While-Schleife

Ich versuche, mehrere allgemeine Aufgaben zu automatisieren, für die ich mich per SSH mit einem Remote-Server verbinde. Dazu verwende ich PuTTY und dessen Option „Remote-Befehl“ (Verbindung > SSH) in mehreren gespeicherten Sitzungen. Mein Remote-Befehl sieht ungefähr so ​​aus:

~/scripts/test; $SHELL -l

Das ausgeführte Skript ist je nach gespeicherter Sitzung unterschiedlich und führt unterschiedliche Aufgaben aus. $SHELL -lhält die PuTTY-Sitzung aktiv, nachdem die Ausführung des Skripts abgeschlossen ist.

All dies funktioniert für die meisten Skripte, die ich ausführe, einwandfrei. Ich habe jedoch eines, das eine While-Schleife verwendet, um eine Reihe von Befehlen auszuführen, bis es mit Strg+C beendet wird. Das Skript startet einwandfrei, aber die PuTTY-Shell bleibt nach der Beendigung nicht aktiv. $SHELL -lscheint nicht ausgeführt zu werden.

Ein Beispielskript mit diesem Verhalten sieht wie folgt aus:

while true; do
echo "."
sleep 2
done

Folgendes funktioniert manuell ausgeführt einwandfrei. Beim zweiten Befehl sehe ich die erwartete Ausgabe:

~/scripts/test; echo "done"

Der zweite Befehl des PuTTY-„Remote-Befehls“ wird jedoch nicht ausgeführt. Wenn ich den Remote-Befehl so ändere, dass er ein enthält echo, wird er tatsächlich nicht angezeigt.

~/scripts/test; echo "done"; $SHELL -l

Meine Frage ist also: Warum wird der zweite Befehl in der Liste vom Remote-Befehl nicht ausgeführt, während dies bei der manuellen Ausführung der Fall ist? Und, was noch wichtiger ist, was kann ich dagegen tun?

Falls es relevant ist: Ich verwende PuTTY auf Ubuntu 14.04.

Antwort1

Wenn Sie puttyoder ssh– ich glaube, in diesem Zusammenhang besteht kein Unterschied – einen Befehl ausführen, der auf dem Remote-System ausgeführt werden soll, führt der Remote-SSH-Server den Befehl als Shell-Befehl aus:

/bin/bash -c '~/scripts/test; $SHELL -l'

Sie haben also eine bashInstanz auf dem Remote-System, die diese Pipeline ausführt. Sie haben auch eine weitere bashInstanz, die von der ersten Instanz gestartet wird und dieses „Test“-Skript ausführt.

Wenn Sie Strg-C drücken, puttywird das Zeichen an das Remote-System gesendet, wo es von Ihrem TTY als Unterbrechungszeichen interpretiert wird. Dies führt dazu, dass ein SIGINT (Unterbrechungssignal) an Prozesse gesendet wird, die an das TTY angeschlossen sind. Dies unterbricht beide Shell-Prozesse und führt dazu, dass beide beendet werden. Sie möchten, dass die übergeordnete Shell-Instanz SIGINT ignoriert.

Der Bash-Befehl zum Ignorieren von SIGINT lautet:

trap "" INT

Um SIGINT für Ihre Pipeline zu deaktivieren, ändern Sie Ihren ursprünglichen Befehl wie folgt:

trap '' INT; ~/scripts/test; $SHELL -l

Dies deaktiviert jedoch auch SIGINT für untergeordnete Prozesse, wodurch das „Test“-Skript immun gegen Strg-C wäre. Sie müssen also SIGINT für das Testskript erneut aktivieren. Der Befehl dafür lautet:

trap INT

Sie können diese Zeile dem Testskript selbst oder der Pipeline hinzufügen:

trap '' INT; ( trap INT; ~/scripts/test ); $SHELL -l

Wenn Sie jetzt Strg-C drücken, sollten Sie den „Test“-Prozess unterbrechen, nicht jedoch den übergeordneten Prozess, der die Befehlspipeline ausführt.

Sie können dies testen, ohne Putty oder SSH zu verwenden. Führen Sie einfach diese Befehle aus und drücken Sie Strg-C, während „Sleep“ ausgeführt wird:

bash -c 'sleep 15; echo foo'                  # Ctrl-C kills sleep; doesn't print "foo"
bash -c 'trap "" INT ; sleep 15; echo foo'    # Ctrl-C has no effect
bash -c 'trap "" INT; ( trap INT; sleep 15 ); echo foo'    # Kills sleep, prints "foo"

Antwort2

Strg+C für den Putty-Remote-Befehl unterbricht tatsächlich die SSH-Sitzung, daher ist zu erwarten, dass die verbleibenden Remote-Befehle nicht ausgeführt werden. Wenn Ihr Ziel nur darin besteht, die Sitzung aktiv zu halten, sollte Ihre Endlosschleife ausreichen.

verwandte Informationen