Remote Script Execution

Kürzlich war ich in der Situation, dass ich auf einem RaspberryPi ein Script ausführen musste, welches ein angeschlossenes Gerät initialisieren sollte. Soweit erstmal nichts außergewöhnliches:

  • per SSH anmelden
  • Script ausführen
  • fertig

Da diese Initialisierung aber später in einen extern ablaufenden Prozess auf einer anderen Maschine eingebunden werden soll, musste ein Weg her, die Initialisierung aus einem Prozess auf einem anderen (Windows) System anzustoßen.

PuTTY

Bei den Themen Windows und SSH landet man natürlich zwangsläufig bei PuTTY.
PuTTY bietet verschiedene Möglichkeiten auf einem entfernten System mit aktiviertem SSH Zugang Skripte (bzw. beliebige Kommandos) auszuführen. Um dies zu demonstrieren legt man zuerst ein Python Skript auf dem Zielsystem an. Folgender einfacher Inhalt soll für eine Demonstration ausreichen:

#!/usr/bin/python

print("Initialization successful...")
exit(0)

Die neu erstellte Datei noch ausführbar machen (chmod +x ...) und schon kann es losgehen.
Mit dem Kommandozeilenparameter m kann man PuTTY nun eine lokale Datei übergeben, deren Inhalt als Kommandos innerhalb der aufzubauenden Verbindung interpretiert werden sollen. Angenommen das oben gezeigte Skript liegt als initialize.py im home Verzeihnis des Benutzers, der per SSH am entfernten System angemeldet wird, dann würde die folgende Datei remote_commands.txt

./initialize.py

mittels folgender Kommandozeile (der Pfad für den Parameter m muss natürlich an die jeweiligen Gegebenheiten angepasst werden)

putty -ssh -l fez -pw <PASSWORD> -m d:/tools/putty/remote_commands.txt 192.168.178.36

an PuTTY übergeben, zu folgendem Ergebnis führen:

Command file result

Die Ausführung eines Kommandos auf einem entfernten System funktioniert also soweit.
Allerdings hat diese Vorgehensweise auch Nachteile.
Zuerst ist es nicht sonderlich komfortabel alle auszuführenden Kommandos in speziellen Kommandodateien abzulegen, die dann als PuTTY Kommandozeilenparameter übergeben werden müssen. Bei einem oder zwei zu verwendenden Kommandos mag das noch gehen, aber irgendwann wird diese Herangehensweise unübersichtlich.
Der weitaus größere Nachteil ist aber der, dass man keine Möglichkeit hat den Exit-Code und somit die erfolgreiche Abarbeitung des oder der Kommandos zu überprüfen.

Auftritt Plink.
Plink (PuTTY Link) stellt eine kommandozeilenbasierte Schnittstelle zum PuTTY Backend dar und ist von der Funktionalität ähnlich dem von UNIX Systemen bekannten ssh.
Um die Funktionsweise von Plink zu demonstrieren modifiziert man zuerst das eben erstellte Python Skript auf dem Zielsystem folgendermaßen:

#!/usr/bin/python

print("Initialization failed...")
exit(42)

Dieses modifizierte Skrip soll eine fehlgeschlagene Initialisierung auf dem Zielsystem simulieren. Dazu wird der Exit-Code des Skripts auf einen Wert ungleich 0 geändert. Bei der bisherigen Vorgehensweise des Aufrufs über den m Parameter und die Datei remote_commands.txt hätte man ohne weiteres keine Möglichkeit die erfolgreiche Abarbeitung der gewünschten Kommandos automatisiert zu überprüfen.
Führt man das Skript aber nun über folgendes plink Kommando aus

plink.exe -ssh -pw <PASSWORD> fez@192.168.178.36 ~/error42.py

führt dies zu folgender Ausgabe:

plink result

Über das bekannte

echo %ERRORLEVEL%

ist es nun auch möglich, den Rückgabewert der Kommandoausführung abzufragen und somit die erfolgreiche Abarbeitung automatisiert zu überprüfen.

plink errorcode

Geschrieben 2015-09-14