python-3.x - 如何从 pexpect.spawn() 收集所有输出
问题描述
目前,c.read() 函数仅从我正在调用的程序的输出中返回值,并且不收集在交互部分发生的情况。(换句话说:等待用户名和密码)。由于该部分可能发生错误,因此我需要在调用 cmd 后收集所有输出。
使用运行命令工作正常。我正在尝试转换为使用 expect.spawn(),因为它看起来非常接近 ssh 版本的 expect。当前 run() 方法可以正常工作,因为它可以在本地工作。我找不到可以返回整个输出的 getOutput() 类型函数。
import pexpect
class Expect( ):
def Do( self, cmd, program: list = [], timeout: int = 20 ):
# result = run( cmd, events=program, timeout=timeout).decode()
result = ''
c = pexpect.spawn( cmd, encoding='utf-8', timeout=timeout )
for curItem in program:
# print( 'wait: ' + curItem[0] + ' resp: ' + curItem[1])
c.expect( curItem[0] )
c.sendline( curItem[1] )
# result += c.read()
result += c.read()
print ( 'res: ' + str(result) )
return result
cmd = 'fmsadmin list files -s'
prog = [('username \\(.+\\):', 'yourUN\n'), ('password:', 'yourPW\n')]
res = Expect().Do( cmd, prog ) # Returns everything
# use results to verify functionality
结果
ID File Clients Size Status Enabled Extended Privileges Encrypted
1 FMServer_Sample.fmp12 0 905216 Normal fmapp fmxml fmphp fmwebdirect No
当我期待
username (yourUN):yourUN
password:
ID File Clients Size Status Enabled Extended Privileges Encrypted
1 FMServer_Sample.fmp12 0 905216 Normal fmapp fmxml fmphp fmwebdirect No
更新
我在 c.sendline( curItem[1] ) 下添加了 result += c.before + c.after 现在返回: c.sendline( curItem[1] )
username (yourUN): yourUN
password:
ID File Clients Size Status Enabled Extended Privileges Encrypted
1 FMServer_Sample.fmp12 0 905216 Normal fmapp fmxml fmphp fmwebdirect No
不幸的是,仍然存在两个问题。1 还有其他值,例如输出中的返回值,如果我提供无效密码,我会在没有应用程序返回值的情况下返回调试详细信息。我得到:
before (last 100 chars): '\r\n/usr/local/bin/fmsadmin: Permission denied, please try again.\r\nusername (yourUN):'
after: <class 'pexpect.exceptions.TIMEOUT'>
match: None
match_index: None
etc
所以简而言之,我正在寻找来自 CLI 的完整返回值,就像我手动完成时返回的一样。这就是 run() 的作用。
解决方案
Pexpect 就像最初的 TCL Expect 一样,很难获得会话输入和输出的正确部分。挑战在于格式化您的搜索模式以匹配它应该匹配的内容,并且仅此而已。要使其正常工作,您所要做的就是用,和属性解析返回的对象。before
after
match
也就是说,Pexpect 获得了终端显示的所有内容,包括命令和输出。幸运的是,密码没有显示出来,不幸的是,Pexpect 看不到它们。
from pexpect import spawn, EOF # Better import only needed methods
process = spawn('bash', encoding='utf-8')
process.expect('$') # Expects terminal prompt
process.sendline('read -p "username: " var')
process.expect('\nusername: ') # Gets command, newline and username prompt
process.sendline('me')
process.expect('[^\n]*\n.*$') # Gets typed string, newlind and terminal prompt
print(process.match.group(0)) # Prints whole string matched
me # User typed
me@myhost ~ $ # Terminal prompt
process.sendline('read -sp "password: " var') # Note the '-s' for 'silent'
process.expect('\npassword: ')
process.sendline('my_passwd')
process.expect('.*$') # Trying to match a newline just doesn't work
print(process.match.group(0))
me@myhost ~ $ # Only terminal prompt
process.sendline('exit')
process.expect(EOF)
所以你应该知道你想解决什么样的问题。你为什么要收集所有发送和返回的东西,包括密码?
顺便说一句,您可能已经知道代码中的纯密码问题。我的建议getpass
::
from getpass import getpass
password = getpass()
<Then use the password>
BTW 2,以防万一,有文档。
推荐阅读
- java - AspectJ Maven 插件获取 java.lang.NullPointerException
- vb.net - F10 和正常 RUN 给出不同的输出
- typo3 - 从打字稿中的cObject复制数据
- django - 在多个视图中重用查询集
- python - Python 中的 Excel AVERAGEIF 使用替代表格布局
- go - 写入 CON(Windows 控制台)不会打印到 STDOUT(控制台)
- firebase - 图片网址为空
- javascript - React 路由更改 URL 但不加载组件
- angular - Angular 9 - 解析给定网址的每个参数
- elasticsearch - 尝试过滤该字段可能不存在的一些 Elasticsearch 结果