2016-08-16 1 views
2

Ich versuche, ein Cross-Plattform-Tool zu schreiben, das bestimmte Befehle ausführt, erwartet bestimmte Ausgabe zur Überprüfung und sendet bestimmte Ausgabe (wie Benutzername/Passwort) für die Authentifizierung.Windows Alternative zu Pexpect

Unter Unix konnte ich erfolgreich ein Python-Tool programmieren, das die pexpect-Bibliothek verwendet (über pip install pexpect). Dieser Code funktioniert perfekt und ist genau das, was ich versuche zu tun.

self.process = pexpect.spawn('/usr/bin/ctf', env={'HOME':expanduser('~')}, timeout=5) 
self.process.expect(self.PROMPT) 
self.process.sendline('connect to %s' % server) 
sw = self.process.expect(['ERROR', 'Username:', 'Connected to (.*) as (.*)']) 
if sw == 0: 
    pass 
elif sw == 1: 
    asked_for_pw = self.process.expect([pexpect.TIMEOUT, 'Password:']) 
    if not asked_for_pw: 
     self.process.sendline(user) 
     self.process.expect('Password:') 
    self.process.sendline(passwd) 
    success = self.process.expect(['Password:', self.PROMPT]) 
    if not success: 
     self.process.close() 
     raise CTFError('Invalid password') 
elif sw == 2: 
    self.server = self.process.match.groups()[0] 
    self.user = self.process.match.groups()[1].strip() 
else: 
    info('Could not match any strings, trying to get server and user') 
    self.server = self.process.match.groups()[0] 
    self.user = self.process.match.groups()[1].strip() 
info('Connected to %s as %s' % (self.server, self.user)) 

Ich versuchte, läuft die gleiche Quelle auf Windows (Ändern /usr/bin/ctf zu c:/ctf.exe) und ich erhalte eine Fehlermeldung:: Ich habe für Proof-of-concept unten einen kleinen Ausschnitt aus meinem Code versehen

Traceback (most recent call last): 
    File ".git/hooks/commit-msg", line 49, in <module> with pyctf.CTFClient() as c: 
    File "C:\git-hooktest\.git\hooks\pyctf.py", line 49, in __init__ 
    self.process = pexpect.spawn('c:/ctf.exe', env={'HOME':expanduser('~')}, timeout=5) 
    AttributeError: 'module' object has no attribute 'spawn' 

nach dem pexpectdocumentation:

pexpect.spawn und pexpect.run() sind nicht verfügbar unter Windows , da sie auf Unix-Pseudoterminals (ptys) beruhen. Plattformübergreifender Code darf diese nicht verwenden.

Das führte mich auf meiner Suche nach einem Windows-Äquivalent. Ich habe das beliebte winpexpect Projekt here und sogar eine neuere (gegabelte) Version here versucht, aber keines dieser Projekte scheint zu funktionieren. Ich verwende die Methode:

self.process = winpexpect.winspawn('c:/ctf.exe', env={'HOME':expanduser('~')}, timeout=5) 

nur zu sitzen und die Eingabeaufforderung nichts tun (es scheint, als ob es in der winspawn Methode gefangen ist). Ich frage mich, was ich sonst noch tun könnte, um ein Python-Skript zu programmieren, das mit der Kommandozeile interagiert, um den gleichen Effekt wie unter Unix zu erreichen. Wenn ein geeignetes funktionierendes Windows-Version pexpect Skript nicht existiert, welche anderen Mittel könnte ich verwenden, um darüber zu gehen?

+0

Ich vermute, dies ist die Passwortabfrage, die Ihre Probleme unter Windows verursacht. Ich hatte eine Menge Probleme damit, ein Passwort an einen 'PLINK'-Befehl (ssh) zu senden und gab es schließlich auf. Ich persönlich würde 'subprocess.Popen' mit Zeilenscans (manuellem Code) verwenden, um das zu tun. Kannst du nicht wenigstens einen Benutzer/ein Passwort an deinen Befehl übergeben? –

+0

winpexpect verwendet Rohre für die Standardgriffe. In diesem Fall wechseln die meisten Befehlszeilenprogramme zur vollständig zwischenspeichernden Standardausgabe. Sie sehen also nur die Ausgabe, wenn der Puffer voll und leer ist. Typischerweise ist der Puffer 4 KiB. – eryksun

+0

Wenn Sie an dieselbe Konsole wie der untergeordnete Prozess angefügt sind, können Sie die API der Windows-Konsole verwenden, um direkt in den Eingabepuffer zu schreiben und vom Bildschirmpuffer zu lesen. Sie können sogar einen neuen, leeren Bildschirmpuffer erstellen, der entweder vorübergehend als aktiver Bildschirmpuffer festgelegt oder von einem Dateideskriptor referenziert und als 'stdout' an' subprocess.Popen' übergeben wird. – eryksun

Antwort

1

Anstatt pexpect.spawn zu verwenden, können Sie pexpect.popen_spawn.PopenSpawn für windows verwenden.

child = pexpect.popen_spawn.PopenSpawn('cmd', timeout=1) 
child.send('ipconfig') 
child.expect('Wireless', timeout=None)