【发布时间】:2016-08-16 13:56:44
【问题描述】:
我正在尝试编写一个跨平台工具来运行特定命令,期望某些输出进行验证,并发送某些输出(如用户名/密码)进行身份验证。
在 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/ctf 更改为 c:/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.spawn和pexpect.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 脚本,我可以使用什么其他方法来解决这个问题?
【问题讨论】:
-
我怀疑这是导致您在 Windows 上出现问题的密码提示。我在向
PLINK(ssh) 命令发送密码时遇到了很多麻烦,最后放弃了。我个人会使用带有行扫描(手动代码)的subprocess.Popen来做到这一点。您至少不能将用户/密码传递给您的命令吗? -
winpexpect 使用管道作为标准句柄。在这种情况下,大多数命令行程序切换到完全缓冲标准输出,因此您只会在缓冲区填满并刷新时看到输出。通常缓冲区为 4 KiB。
-
如果您与子进程连接到同一个控制台,那么您可以使用 Windows 控制台 API 直接写入其输入缓冲区并从屏幕缓冲区读取。您甚至可以创建一个新的空屏幕缓冲区,可以将其临时设置为活动屏幕缓冲区或由文件描述符引用并作为
stdout传递给subprocess.Popen。
标签: python windows command-line-interface pexpect