pexpect获取远端命令执行结果

  

类比于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

 

posted @ 2019-01-18 16:51  子厚。  阅读(5413)  评论(0编辑  收藏  举报