类比于shell的expect, python中使用pexpect模块来模拟用户和终端交互。有的时候使用pexpect.sendline发送命令后,在各种条件影响下, 可能并不能保证命令在远端服务器执行成功(例如sftp下执行远端rename/rm,实际文件可能并未成功改名/删除)。这个时候就可能需要获取命令执行结果,然后分析结果来对命令的执行状态进行最终确认!
pexpect模块中可以通过pexpect.before/pexpect.buffer获取命令执行结果:
pexpect.buffer -- 动态保存每一次expect后的所有内容. before/after都依赖此内容; pexpect.before -- 匹配到的关键字之外的字符;expect后会设置before/after, 具体参考附录,摘录一段文字如下:
There are two important methods in Pexpect – expect() and send() (or sendline() which is like send() with a linefeed). The expect() method waits for the child application to return a given string. The string you specify is a regular expression, so you can match complicated patterns. The send() method writes a string to the child application. From the child’s point of view it looks just like someone typed the text from a terminal. After each call to expect() the before and after properties will be set to the text printed by child application. The before property will contain all text up to the expected string pattern. The after string will contain the text that was matched by the expected pattern. The match property is set to the re match object.
测试 -- 模拟sftp登陆后然后执行ls命令查看远端路径
linux:~ # tree /root/sftp/ /root/sftp/ ├── csv │ ├── 1000.csv │ └── 3000.csv └── dat ├── 1000.dat └── 3000.dat 2 directories, 4 files linux:~ #
linux:~ # cat pexpect_test.py import os import sys import pexpect def pexpect_get_command_result(command, process, prompt = 'sftp>'): process.sendline('') # 发送空行, 初始环境 process.expect(prompt) process.buffer = "" # 清空buffer, 防止互相影响 process.sendline(command) process.expect(prompt) # expect后得到的expect.before就是命令和执行结果 return process.before.strip() # 返回结果 def pexpect_connect(): process = pexpect.spawn('sftp 127.0.0.1', timeout=30) index = process.expect(["assword: ", "yes/no", pexpect.EOF, pexpect.TIMEOUT]) if index not in [0, 1]: print "[-] sftp login failed, due to TIMEOUT or EOF" return None if 1 == index: process.sendline("yes") process.expect("assword: ") process.sendline('passwd') return process if __name__ == '__main__': process = pexpect_connect() if process == None: sys.exit(-1) allpath = ['/root/sftp/dat', '/root/sftp/csv'] for path in allpath: print pexpect_get_command_result('ls ' + path, process) process.sendline("bye") process.close(force = True) linux:~ #
linux:~ # python pexpect_test.py ls /root/sftp/dat /root/sftp/dat/1000.dat /root/sftp/dat/3000.dat ls /root/sftp/csv /root/sftp/csv/1000.csv /root/sftp/csv/3000.csv linux:~ #
参考
https://pexpect.readthedocs.io/en/stable/ http://www.noah.org/python/pexpect/ https://www.cnblogs.com/zz27zz/p/7918717.html 引用出处: https://pexpect.readthedocs.io/en/stable/overview.html?highlight=pexpect.buffer