Zeilen nach Popen werden nicht mehr aufgerufen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
snakemake
User
Beiträge: 32
Registriert: Sonntag 6. Juni 2010, 19:20

Hallo,

Ich will eine ssh-Verbindung zu einem entfernten Rechner erstellen und dort eine Serveranwendung starten (iperf). Dazu haben ich Popen vom Modul subprocess gemacht und Folgendes geschrieben:

Code: Alles auswählen

f = open(filename, "w")
ssh_return = subprocess.Popen(cmd, shell = True, stdout = f).communicate()[0]
f.close()
"cmd" ist der Befehl, der zuerst eine ssh-Verbindung zum entfernten rechner aufbaut und anschließend dort den Server startet. Ich bin interessiert an den Ausgaben des Servers, will ihn aber nicht stoppen. Sie sollen in einer Datei gespeichert sein, die hier "filename" heißt. Nachdem subprocess.Popen aufgerufen wurde, kommen wir jedoch nicht weiter, erreichen also die Zeilen danach nicht.

Meine Frage ist nun, warum wir sie nicht erreichen und wie man es lösen kann.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Der `stdout` muss eine `subprocess.PIPE` sein, und das `ssh_return` kannst du dann in eine Datei schreiben. In der Doku zum subprocess-Modul ist doch ein Beispiel... (http://docs.python.org/library/subproce ... -backquote)
„Lieber von den Richtigen kritisiert als von den Falschen gelobt werden.“
Gerhard Kocher

http://ms4py.org/
busfahrer
User
Beiträge: 111
Registriert: Donnerstag 9. Oktober 2008, 17:42

Hallo

ich bin eher der unwissende und hab mal versucht das mit der Ausgabe von 'cat /etc/fstab' auf meiner s100 in die Datei zu schreiben und das hat funktioniert.Sollte dann ja bei dir ähnlich laufen.

Code: Alles auswählen

#!/usr/bin/env python

import subprocess

with open("return.txt", "w") as f:
    cmd = ["ssh", "USER@IP", "cat", "/etc/fstab"]
    ssh = subprocess.Popen(cmd, stdout=subprocess.PIPE)
    output = ssh.stdout.read()
    f.write(output)
Gruß...busfahrer
Alles wird gut ;-)
ichisich
User
Beiträge: 134
Registriert: Freitag 1. Januar 2010, 11:52

Hi,
das Ganze wird wie ich meine folgendermaßen schöner:

Code: Alles auswählen

from subprocess import Popen, PIPE # evt noch STDOUT
p = Popen(cmd, shell = True, stdout=PIPE, stderr=PIPE )
with open("return.txt", "w") as f:
    f.write(p.communicate()[0])
Wenn Du es so machst:

Code: Alles auswählen

stderr=STDOUT 
wird alles in stdout geschrieben und dir geht nix verloren.

In der Doku wird davor gewarnt stdout & stderr mit write() zu erschlagen falls der Prozess sehr gesprächig ist.
Warning

Use communicate() rather than .stdin.write, .stdout.read or .stderr.read to avoid deadlocks due to any of the other OS pipe buffers filling up and blocking the child process.

hier
Gruß
snakemake
User
Beiträge: 32
Registriert: Sonntag 6. Juni 2010, 19:20

Hallo,
all eure Lösungen hab ich ausprobiert, doch nichts funktioniert.

Ich starte auf dem enzfernten Rechner einen iperf-Server. Dieser läuft die ganze Zeit. Ich hab über prints herausgefunden, dass mein Skript zwar bis nach dieser Zeile kommt:

Code: Alles auswählen

p = Popen(cmd, shell = True, stdout=PIPE, stderr=PIPE )
,
aber sobald er das

Code: Alles auswählen

f.write(p.communicate()[0])

erreicht, geht halt nichts weiter.
BlackJack

@snakemake: `communicate()` kehrt erst zurück, wenn alle Ausgaben vom anderen Programm gelesen sind und das andere Programm beendet ist. Wenn das ständig weiterläuft, kannst Du diese Methode nicht verwenden.
snakemake
User
Beiträge: 32
Registriert: Sonntag 6. Juni 2010, 19:20

Gibt es denn keine andere Möglichkeit? Ich will nämlich gleich nach dem Server die Clienten starten, muss als zu den Zeilen nach communicate... :(
BlackJack

@snakemake: Verwende doch einfach eine offene Datei für das `stdout`-Argument und lass `communicate()` weg. Das war im ersten Beitrag sowieso in der Kombination unsinnig -- wenn Du die Ausgabe in eine Datei umlenkst, kannst Du sie mit `communicate()` ja nicht gleichzeitig abfragen.
snakemake
User
Beiträge: 32
Registriert: Sonntag 6. Juni 2010, 19:20

Das mit dem stdout-Argument hab ich auch gemacht. Hat ne Fehlermeldung erzeugt. Allerdings habe ich im command selbst einfach eine Umleitung in eine Datei gemacht :D (also mit einem einfachen ">"). Da ja ein Kindprozess erzeugt wurde, wird die Umleitung gemacht, aber währenddessen kehrt mein Hauptprozess normal zu den nächsten Anweisungen nach Popen und die Iperf-Clienten werden gestartet :)
Antworten