pexpect用來啟動子程式,使用正則表達式對程式輸出做出特定響應,以此實現與其自動交互的python模塊,當然我們可以使用他來做ssh登陸,ssh模塊登陸還有一個基於python實現遠程連接,用於ssh遠程執行命令,文件傳輸等功能的ssh客戶端模塊paramiko。 在開發時也經常會使用pexpe ...
pexpect用來啟動子程式,使用正則表達式對程式輸出做出特定響應,以此實現與其自動交互的python模塊,當然我們可以使用他來做ssh登陸,ssh模塊登陸還有一個基於python實現遠程連接,用於ssh遠程執行命令,文件傳輸等功能的ssh客戶端模塊paramiko。
在開發時也經常會使用pexpect模塊,所以這裡簡單介紹一下pexpect。
run():直接執行命令返回結果和狀態
run里有一個command參數,可以直接寫命令然後拿到命令返回的狀態和結果。
In [2]: import pexpect In [3]: pexpect.run("ls /tmp/")
我的/tmp下的東西有點多,已經刪除了部分,此時只拿到了執行的結果但是沒有拿到執行的狀態。
In [4]: pexpect.run("ls /tmp", withexitstatus=1)
withexitstatus為1則表示需要返回執行狀態,預設不返回。
執行狀態為:
返回的結果是一個元組,下標1的值為0即執行成功,非0則為執行失敗。
命令不存在時會報錯,
命令存在但是執行失敗則列印錯誤信息,得到非0狀態碼。
spawn
啟動子程式,有豐富的方法實現對子程式的控制。
比如我們使用spawn進行ssh連接:
In [7]: ssh_aliyun = pexpect.spawn('ssh 120.79.254.225')
In [8]: ssh_aliyun.expect("password:")
生成一個實例對象,使用在expect期望的結果中我們可以使用完全匹配也可以使用正則匹配。
當匹配成功以後會返回狀態碼0,匹配欄位不存在,則程式阻塞,知道timeout程式會報錯。
註:expect中的$就是$不是正則表達式里的以某某結尾的意思。
當然我們不希望匹配不成功而導致程式崩潰,expect中也可以填入錯誤狀態,或者多個期待值,放在一個列表中。
In [18]: ssh_aliyun = pexpect.spawn('ssh 120.79.254.225') In [19]: ssh_aliyun.expect([pexpect.TIMEOUT, pexpect.EOF, "password:"]) Out[19]: 2
返回的結果為列表下標索引值。timeout則結果為0.
對於剛纔的實例,我對阿裡雲伺服器發起ssh遠程連接,需要進行密碼校驗,那麼我們如何進行命令鍵入呢。
我們可以使用send(),sendline(),sendcontrol(char)。向子程式發送指令。前兩種就是發送指令,後一種發送控制符(比如發送ctrl+c中斷命令)。
密碼登陸的ssh腳本
import pexpect def login_ssh_passwd(port="",user="",host="",passwd=""): '''函數:用於實現pexepect實現ssh的自動化用戶密碼登錄''' # print 'ssh -p %s %s@%s' % (port,user, host) if port and user and host and passwd: ssh = pexpect.spawn('ssh -p %s %s@%s' % (port,user, host)) i = ssh.expect(['password:', 'continue connecting (yes/no)?'], timeout=5) if i == 0 : ssh.sendline(passwd) elif i == 1: ssh.sendline('yes\n') ssh.expect('password: ') ssh.sendline(passwd) index = ssh.expect (["#", pexpect.EOF, pexpect.TIMEOUT]) if index == 0: print("logging in as root!") #終端直接接管子程式會話,在終端直接操控ssh # ssh.interact() elif index == 1: print("logging process exit!") elif index == 2: print("logging timeout exit") else: print("Parameter error!")
通過密鑰方式登陸
def login_ssh_key(keyfile="",user="",host="",port=""): '''函數:用於實現pexepect實現ssh的自動化密鑰登錄''' if port and user and host and keyfile: ssh = pexpect.spawn('ssh -i %s -p %s %s@%s' % (keyfile,port,user, host)) i = ssh.expect( [pexpect.TIMEOUT,'continue connecting (yes/no)?'], timeout=2) # print '...................................',0 if i == 1: ssh.sendline('yes\n') index = ssh.expect (["#", pexpect.EOF, pexpect.TIMEOUT]) else: index = ssh.expect (["#", pexpect.EOF, pexpect.TIMEOUT]) if index == 0: print("logging in as root!") ssh.interact() elif index == 1: print("logging process exit!") elif index == 2: print("logging timeout exit") else: print("Parameter error!")
使用pexpect實現ssh遠程登陸存在一些問題,依賴終端來完成登陸。在不同的登陸環境(系統不一致,埠不一致等)相容性比較差。
在資產管理的登陸掃描探測的具體環境中不適合直接使用pexpect來操作。