2014-10-16 9 views
5

Ich habe ein Python-Skript, das ich benutze, um Befehle parallel über mehrere Hosts mit dem Python-Subprozess-Modul auszuführen. Es wickelt SSH, und macht im Grunde ein Aufruf wie folgt:Terminal durcheinander (keine neuen Zeilen angezeigt) nach dem Ausführen von Python-Skript

output = subprocess.Popen(["/bin/env", env, "/usr/bin/ssh", "-t", "%[email protected]%s" % (user, host), "--", command], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() 

Der effektive Befehl wie folgt ausgeführt wird:

/bin/env TERM=$TERM:password /usr/bin/ssh -t "%[email protected]%s" % (user, host), "--", command 

Es funktioniert gut, außer ich einen intermittierenden Fehler, wo mein Terminal messed aufsteht (verliert Zeilenumbrüche) nach dem Ausführen des Skripts. Ein "Reset" von der Kommandozeile behebt es, aber ich bin mir nicht sicher, wie das genau passiert. Ich bemerkte, dass manchmal am Ende des ersten Eintrags im Tupel ein "\ r \ n" steht, und manchmal ist es nicht da. Siehe folgende, speziell "Zugriff verweigert \ r \ n":

**** Okay output **** 
[[email protected]/home/user]# ./command.py hosts.lists "grep root /etc/shadow" 
Running command "grep root /etc/shadow" on hosts in file "hosts.test" 
('grep: /etc/shadow: Permission denied\r\n', 'Connection to server1.example.com closed.\r\n') 
('grep: /etc/shadow: Permission denied\r\n', 'Connection to server2.example.com closed.\r\n') 
[[email protected]/home/user]# 


**** Output causes terminal to not display newlines **** 
[[email protected]/home/user]# ./command.py hosts.list "grep root /etc/shadow" 
('grep: /etc/shadow: Permission denied\r\n', 'Connection to server1.example.com closed.\r\n') 
('grep: /etc/shadow: Permission denied\n', 'Connection to server2.example.com closed.\r\n') 
           [[email protected]/home/user]# [[email protected]/home/user]# [[email protected]/home/user] 

Der zweite Ausgang geringfügig modifiziert wurde, zeigt jedoch die fehlenden "\ r", und wie meine Prompt bekommt "wacked" nach dem Ausführen des Skripts.

Ich denke, das ist mit der Verwendung der Option "-t" in meinem Unterprozessbefehl verwandt. Irgendwie verliere ich das. Wenn ich die "-t" -Option entferne, verschwindet dieses Problem, aber lange Rede kurzer Sinn, ich brauche es für die Weitergabe von Umgebungsvariablen zur Verwendung auf dem entfernten Rechner (Ich benutze die TERM-Variable, um das Passwort des Benutzers zu übergeben sudo, weil ich nicht annehmen kann, dass AcceptEnv eine beliebige Variable erlaubt, die den entfernten sshd-Server weiterleitet; ich mache das, um zu vermeiden, das Passwort in der Befehlszeile zu übergeben, das in der Prozessliste auf dem entfernten Rechner erscheint).

Frage nur, ob jemand einen Weg kennt, um dies zu umgehen, ohne die Option "-t" zu entfernen?

UPDATE:. Es ist wie Einstellungen nach dem Ausführen des subprocess.Popen (...) verändert bekommen meine tty sieht kommunizieren() Befehl in meinem Skript, unabhängig davon, ob ich die Ausgabe tatsächlich drucken zu Bildschirm. Das finde ich wirklich komisch. Hier ist die vor/nach Unterschieden in meiner tty config (von stty -a):

-ignbrk brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff 
-ignbrk brkint ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff 


opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 
-opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 

isig icanon -iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt 
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt 

Ich frage mich, wie die Kommunikation zu stoppen() von änderte meinen Terminal-Einstellungen? Ist es möglich, oder ist das ein Fehler?

+0

Benötigt der * Befehl * tatsächlich die Option '-t' ssh? – jfs

+0

'.communicate()' ändert Ihre Einstellungen nicht. Versuchen Sie einige Curses Python-Skript, das seine Einstellungen beim Beenden als * Befehl * nicht wiederherstellen und sehen, ob Sie den Fehler verlässlich reproduzieren können, d. H. Das Skript ein Flag akzeptieren, ob tty beim Beenden wiederhergestellt werden soll oder nicht. – jfs

+0

zum Beispiel, Sie könnten nichts tun in der 'endlich'-Block, wenn eine' --no-restore' Flag in [dieses Skript] übergeben wird (http://StackOverflow.com/a/327072/4279) – jfs

Antwort

4

Ich hatte das gleiche Problem in einem Perl-Skript. Um das Problem zu lösen, musste ich die aktuellen Einstellungen des lokalen Terminals speichern (um es am Ende des Skripts wiederherzustellen) und "sty -raw" vor dem Ausführen des Remote-Befehls vorsetzen.

So in Perl:

#Save aktuellen Terminaleinstellungen (Sie können die PID im Dateinamen hinzufügen)

`stty -g> ~/tmp/.currentTtySettings`;

#Execute Remote-Befehl Prepending "Stty -raw"

meine @ out = `ssh -t -q [email protected] "stty -raw; grep root/etc/shadow" `;

#Restore Terminaleinstellungen

`stty \` cat ~/tmp/.currentTtySettings \ ``;

Hoffe es hilft dir!

Andere sehr nützliche Links:

-Detaillierte Erklärung von ssh und tty (Option -t) https://unix.stackexchange.com/questions/151916/why-is-this-binary-file-being-changed

-Einige Perl und ssh Inspiration http://search.cpan.org/~bnegrao/Net-SSH-Expect-1.09/lib/Net/SSH/Expect.pod

-Wie zu vermeiden "-t" für https://unix.stackexchange.com/questions/122616/why-do-i-need-a-tty-to-run-sudo-if-i-can-sudo-without-a-password sudo

0

ich fand, dass

stty sane 

stellt die Konsole wieder her wie zuvor. Ich habe die andere Antwort hier nicht wirklich verstanden, also hilft mir das jemand.

Die Antwort gefunden here.