一、pexpect模塊介紹
Pexpect使Python成為控制其他應用程序的更好工具。可以理解為Linux下的expect的Python封裝,通過pexpect我們可以實現對ssh,ftp,passwd,telnet等命令行進行自動交互,
而無需人工干涉來達到自動化的目的
二、Pexpect的安裝
#方法一: pip3 install pexpect #方法二:源碼安裝 略
三、簡單示例
import pexpect #ssh登錄,賬號root,主機:114.114.114.114,端口5000 child = pexpect.spawn('/usr/binssh root@114.114.114.114 -p 5000') #expect方法等待子程序產生的輸出,判斷是否匹配定義的字符串 child.expect('Password') #匹配后則發送密碼串進行回應 child.sendline('hello123') 注:spawn類無法在windows下運行
如果child.sendline('copy tftp://10.100.255.220/vip_user_list.txt flash:vip_user_list.txt')是一個下載文件命令,而下載過程又比較長,又不想將全局的timeout超時時間統一改太長?
解決方法如下:
child.timeout=1200 #超時時間12分鍾
child.send(下載文件)
chile.expect('#')
child.timeout=30 #執行完下載命令,改回默認超時時間30秒即可
四、pexpect的核心組件
4.1 spawn類
#功能:啟動和控制子應用程序,以下是它的構造函數定義: class pexpect.spawn(command, args=[], timeout=30, maxread=2000, searchwindowsize=None, logfile=None, cwd=NOne, env=None, ignore_sighup=True) #各參數解析 #1. command參數可以使任意已知的系統命令,比如: child = pexpect.spawn('/usr/bin/ftp') #啟動ftp客戶端命令 child = pexpect.spawn('/usr/bin/ssh root@114.114.114.114')#啟動ssh遠程連接命令 child = pexpect.spawn('ls -lattr /tmp') #運行ls顯示/tmp目錄內容命令 #2. args=[] 當子程序需要參數時,可以使用Python列表來代替參數項,如: child = pexpect.spawn('/usr/bin/ftp',[]) child = pexpect.spawn('/usr/bin/ssh',[root@114.114.114.114']) child = pexpect.spawn('ls ' ['-lattr' ,'/tmp']) #3. timeout 為等待結果的超時時間; #4. maxread為pexpect從終端控制台一次讀取的最大字節數 #5.searchwindowsize 為匹配緩沖區字符串的位置,默認是從開始位置匹配 #6.logfile 為寫入到日志(打開文件或者終端sys.stdout),logfile也可單獨出來,如 fout=open('mylog.txt','wb') child.logfile = fout #打印到終端,child.logfile = sys.stdout打印到屏幕(在python3中,打印到屏幕需要在spawn(encodig='utf-8')指定編碼類型),最后記得關掉fout.close()
ps:會存在會話結束,但是保存數據或打印到終端數據不完全問題,解決辦法:延長執行命令的次數,跟時間無關,即多次使用無意義的expect(),send()來讓數據有足夠的時間傳回來保存 注:pexpect無法解析shell命令中的元字符(>,|,*),解決辦法: #方法一: child = pexpect.spawn('/bin/bash -c "ls -l | grep LOG > logs.txt"') child.expect(pexpect.EOF) #方法二: shell_cmd = 'ls -l | grep LOG > logs.txt' child=pexpect.spawn('/bin/bash',['-c',shell_cmd]) child.pexpect(pexpect.EOF) ================================================================================== #expect方法 #expect定義了一個子程序的匹配規則 #方法定義: expect(pattern,timeout=-1,searchwindowsize=-1) #參數介紹 #1.pattern為字符串或正則表達式或pexpect.EOF(指向緩沖區尾部,無匹配項)或pexpect.TIMEOUT(匹配等待超時)或者前四種組成的列表,返回列表的索引值 #2.timeout為等待匹配結果的超時時間,超時會觸發pexpect.TIMEOUT #3.searchwindowsize為匹配緩沖區字符串的位置,默認是從開始位置匹配 #pattern為列表的使用: #方法一: p = pexpect.spawn('xxx') index = p.expect(['good','bad',pexpect.EOF,pexpect.TIMEOUT]) if index == 0: fun1() elif index ==1: fun2() elif index ==2: fun3() elif index==3: fun4() #方法二: p = pexpect.spawn('xxx') index = p.expect(['good','bad']) try: if index ==0: fun1() elif index ==1: fun2() expect EOF: fun3() expect TIMEOUT: fun4() #expect方法里的before和after #before:保存了最近匹配成功的內容,倆次child.expect()之間的內容,不包含pattern部分 #after:保存了最近匹配成功之后的內容,即child.expect(這里面的內容) #before與after例子 import pexpect import sys dhild = pexpect.spawn('ssh root@192.168.2.1') child.expect(['password:']) child.sendline('hello123') print ('before:',child.before) print ('after:',child.after)
========================================================================================== #read相關方法,與expect捕捉相配套使用 send(self,s) #發送命令,不回車 sendline(self,s='') #發送命令,回車 sendcontrol(self,char) #發送控制字符,如child.sendcontrol('c')等價於‘ctrl + c’ sendeof() #發送eof
4.2 run函數
#run格式 pexpect.run(command,timeout=-1,withexitstatus=False,events=None,\ extra_args=None,logfile=None,cwd=None,env=None) #參數解析: command:系統已知命令 event:字典,定義了expect與sendline對應關系 #實例 from pexpect import * child=spawn('scp foo user@example.com:.') child.expect('(?i)password') child.sendline(mypassword) #等同於 from pexpect import * run('scp foo user@example.com:.',events={'(?i)password':mypassword})
4.3 pxssh類
#pxssh格式: class pexpect.pxssh.pxssh(timeout=30,maxread=2000,searchwindowsize=None,logfile=None,cwd=None,env=None) #常見的三種方法 login() #建立ssh連接 logout() #斷開連接 prompt() #等待系統提示符,用於度鞥帶命令執行結束 #pxssh例子:ssh登錄設備執行命令,取回結果 from pexpect import pxssh import getpass try: s=pxssh.pxssh() #創建pxssh對象 hostname=input('hostname:').strip() username=input('username:').strip() password=getpass.getpass('password:').strip() #接收密碼輸入 s.login(hostname,username,password) #建立ssh連接 s.sendline('uptime') #運行uptime命令 s.prompt() #匹配系統提示符 print (s.before.decode'utf-8') #打印出現系統提示符前的命令輸出 s.sendline('ls -l') s.prompt() print (s.before.decode'utf-8') s.sendline('df') s.prompt() print(s.before.decode'utf-8') s.logout() #斷開ssh連接 except pxssh.ExceptionPxssh as e: print ('pxssh failed on login.') print (str(e))