2016-08-16 170 views
2

我想寫一個運行特定命令的跨平臺工具,預計某些輸出驗證,併發送某些輸出(如用戶名/密碼)進行身份驗證。Windows替代pexpect

在Unix上,我成功地編寫了一個使用pexpect庫的Python工具(通過pip install pexpect)。此代碼完美工作,正是我想要做的。我提供我的代碼小節選證明了概念如下:

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)) 

我試圖在Windows上運行同一個源(改變/usr/bin/ctfc:/ctf.exe),我收到一條錯誤消息:

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' 

按照pexpectdocumentation

pexpect.spawnpexpect.run()不可用在Windows ,因爲它們依賴於Unix僞終端(ptys)。跨平臺代碼不得使用這些代碼。

這使我對我的搜索Windows平臺上類似。我曾嘗試流行winpexpect項目here,甚至更近(叉)here版本,但無論這些項目似乎工作。我使用的方法:

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

只能眼睜睜地看着命令提示符什麼也不做(這好像它被困在winspawn方法內)。我想知道還有什麼其他方法可以編寫一個Python腳本來與命令行進行交互,以達到與我在Unix中一樣的效果?如果一個合適的Windows版本pexpect腳本不存在,我可以使用其他方法來解決這個問題?

+0

我懷疑這是在Windows上導致您的問題的密碼提示。將密碼發送到'PLINK'(ssh)命令時遇到了很多麻煩,最後放棄了。我個人使用'subprocess.Popen'和行掃描(手動代碼)來做到這一點。至少你不能將用戶/密碼傳遞給你的命令嗎? –

+0

winpexpect使用管道作爲標準手柄。在這種情況下,大多數命令行程序都會切換到完全緩衝標準輸出,因此只有當緩衝區填滿和刷新時纔會看到輸出。通常緩衝區是4 KiB。 – eryksun

+0

如果您連接到與子進程相同的控制檯,則可以使用Windows控制檯API直接寫入其輸入緩衝區並從屏幕緩衝區中讀取。您甚至可以創建一個新的空白屏幕緩衝區,它可以暫時設置爲活動屏幕緩衝區或由文件描述符引用,並以'stdout'的形式傳遞給'subprocess.Popen'。 – eryksun

回答

1

而不是使用pexpect.spawn您可以使用pexpect.popen_spawn.PopenSpawnwindows

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