1. 程式人生 > >自動化互動指令碼Expect簡單介紹及應用例項

自動化互動指令碼Expect簡單介紹及應用例項

一:事出有因
最近在跟蹤“40G framer link down“這個問題。這個問題,不是很容易復現,只能是一遍遍的reboot 板卡,進入cli命令列,檢視link 狀態。
為了分析原因,需要使 “40G framer link down“,檢視相應資訊。所以只能不停的reboot板卡,直到“link down“為止。這個動作,如果依靠人工來操作,那將會是一個巨大的時間和精力的浪費。
因此,想到了使用自動化處理指令碼來完成這個動作—–expect指令碼。

二:關於Expect指令碼
關於expect指令碼,可以百度出很多介紹。Expect的建立者(creator) Don Libes 寫了一本介紹Expect的書,書名叫《Exploring Expect》。書裡對expect的介紹是:

Expect是一個可以控制 互動式應用(interactive applications) 的程式。
這些互動式應用希望使用者 點選鍵盤 輸入資訊來回應一些互動式的提示。
使用expect,你可以編寫指令碼 用以自動的迴應這些互動提示。
使用自動互動程式,你將有能力解決之前從未想過的問題。

這大概就expect指令碼語言的主要用處,就是為了自動化互動的。
關於expect,書中還寫到:

1: Expect 程式沒有自己的專用語言,可以用C 或者C++來編寫,但是經常使用 Tcl 來寫。
2:Tcl 是一種流行的 內置於應用的 語言。Tcl 提供了很多基礎的命令,比如:if/then/else

,whileset
3:Expect 整合了Tcl的頂層(on the top of Tcl),併為互動式程式提供了額外的命令,比如:expectinteract

三:使用Expect指令碼
【這次先簡略介紹,以後有時間,補充更詳細的解釋】
Expect指令碼最重要的三個命令是:

1. send        send strings to a process;
2. expect      wait for strings for a process;
3. spawn       starts a process;

在實際使用中,還有兩個常用的命令:

4.
interact turn control frome script over to user 5. log_file recode the log with script running

使用expect自動登入伺服器的簡單例子:

vim connect_222.exp
 #!/usr/bin/expect --
 spawn ssh root@10.10.169.222
 expect "password:"
 send "*****"
 interact

簡單介紹一下:
#!/usr/bin/expect –
建立shell的時候,必須在首行指定要是使用的shell。其格式如上所寫。

在通常的shell腳本里面,#用作註釋行;註釋行在shell裡面是不被執行的。
然而,shell指令碼檔案的第一行是特例,#後接 告訴shell使用哪個shell來執行。此處使用expect,所以應該指定expect的位置。
如果不加 ‘– ‘話,執行指令碼需要 expect connect_222.exp
加上‘–‘,只需要在chmod u+x connect_222.exp後,./connect_222.exp即可執行指令碼。

spawn ssh [email protected]
spawn 用來開啟一個程序,方便該語句後面的命令與其互動;

spawn 命令開啟了ssh 程序 ,[email protected]是ssh的引數。
這就像你在命令列上 鍵入ssh [email protected]一樣,ssh連結了10.10.169.222伺服器;
這時,就可以使用expectsend了。

expect “password:”
上條命令打開了ssh程序,該條命令會跟據返回結果搜尋特定的字串,如果匹配,則執行下條語句;若超時未匹配,在會有其他處理結果,後續介紹。

此處的expect是Expect指令碼內建的命令,不等同與Expect。
expect命令通常會等待一個程序的迴應。expect可以等待一個特定的字串,但更多的被用來等待 給定的模式 的任一字串。比如:
expect "yes" {send "yes\r"} "no" {send "no\r"}
例項只匹配特定的字串“password:“
Note: 該例項中expect的匹配,是隻要程序的迴應中出現“password:“則進行下一條命令。更多的情況後需補充。

send “*\r”**
將密碼傳送至程序,注意換行符’\r’.

send命令將一個字串作為引數並且傳送給程序。如果此時Expect正在與一個程式互動,這個字串將會發送至程式,但是初始狀態下,send將會輸出至標準輸出。
本例將Expect正在與ssh互動,則字串將會發送至ssh。如果密碼驗證通過,則此時已經登入了伺服器。指令碼繼續往下執行。

interact
將控制權由指令碼交給使用者。

上面幾行程式碼已經登入到伺服器上了,但此時控制權還在指令碼那裡,使用者是不可以控制伺服器的。如果此時結束指令碼執行,ssh程序將會一併結束,此時又回到執行指令碼的主機目錄。
登入到伺服器後,使用interact上,將控制權交至使用者,使用者即可控制伺服器。
interact命令執行的時候,指令碼停止從腳本里面讀取命令,開始從鍵盤和程序裡讀取。當我們擊鍵時,資料會立即傳送至spawned 程序(本例中即ssh),同時,當程序有輸出時,結果立即傳送至標準輸出,所以我們可以看到結果。
這種現象就好像 Expect並不存在而我們直接與伺服器相連 一樣
當spawned的程序(本例即ssh)終止執行時,interact命令將控制權交給指令碼。如果interact在指令碼末行,則指令碼會自行結束。

關於interact將控制權從使用者交給指令碼,最開始一直沒理解什麼意思,寫了幾個測試程式,也並沒有成功。後來發現是 interact 所在的spawn 出的程序結束之後,才會自動交給指令碼。可以這麼理解:

一個Expect指令碼檔案裡面可以有好多 spawn命令,每一個spawn 執行時都會分離一個執行緒,interact在該spawn執行緒中作用。當該spawn執行緒執行結束,進入到另一個spawn執行緒的時候,控制權交給指令碼。
在同一個spawn作用的範圍內,interact無法將控制權交給使用者。
以上是我的理解,有錯誤的歡迎指出,謝謝!

至此,一個簡單的程式,就完成了。也簡單的介紹了一下。更多的內容後續補上。等有時間吧。