類比於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