2018-07-11 分類:Linux Shell / 系統運維 / 編程開發 閱讀(6670) 評論(0) linux
第一次見expect
這個命令仍是我第一次參加全量上線的時候,那是公司的一個牛人用Shell腳本寫的一套自動部署、MD5 比對、發佈的全量上線工具,沒事的時候,看了下其中的幾個腳本,好多的expect
命令。實在是看不懂這個expect
命令的用法,因此就找時間總結了這篇關於expect
命令的文章。shell
如今有兩臺Linux主機A和B,如何從A主機ssh到B主機,而後在B主機上執行命令,如何使這個過程實現全程自動化?你可能會使用這種方法:編程
ssh admin@10.220.20.15 "ls"
可是這種方式比較笨拙,每次都要輸入密碼,同時並不能執行一些複雜的邏輯或命令。那麼如何實現全程自動化呢?這就要用到今天這篇文章總結的expect
了。運維
expect
是一個免費的編程工具,用來實現自動的交互式任務,而無需人爲干預。說白了,expect
就是一套用來實現自動交互功能的軟件。ssh
在實際工做中,咱們運行命令、腳本或程序時,這些命令、腳本或程序都須要從終端輸入某些繼續運行的指令,而這些輸入都須要人爲的手工進行。而利用expect
,則能夠根據程序的提示,模擬標準輸入提供給程序,從而實現自動化交互執行。這就是expect
!!!工具
在使用expect
時,基本上都是和如下四個命令打交道:spa
命令 | 做用 |
---|---|
send | 用於向進程發送字符串 |
expect | 從進程接收字符串 |
spawn | 啓動新的進程 |
interact | 容許用戶交互 |
send
命令接收一個字符串參數,並將該參數發送到進程。expect
命令和send
命令相反,expect
一般用來等待一個進程的反饋,咱們根據進程的反饋,再發送對應的交互命令。spawn
命令用來啓動新的進程,spawn
後的send
和expect
命令都是和使用spawn
打開的進程進行交互。interact
命令用的其實不是不少,通常狀況下使用spawn
、send
和expect
命令就能夠很好的完成咱們的任務;但在一些特殊場合下仍是須要使用interact
命令的,interact
命令主要用於退出自動化,進入人工交互。好比咱們使用spawn
、send
和expect
命令完成了ftp登錄主機,執行下載文件任務,可是咱們但願在文件下載結束之後,仍然能夠停留在ftp命令行狀態,以便手動的執行後續命令,此時使用interact
命令就能夠很好的完成這個任務。上面對expect
進行了總結,特別是對一些經常使用的命令進行了詳細的說明。下面就經過一些經常使用的expect
腳原本具體的說明如何使用expect
來完成平常的一些工做。命令行
#!/usr/tcl/bin/expect set timeout 30 set host "101.200.241.109" set username "root" set password "123456" spawn ssh $username@$host expect "*password*" {send "$password\r"} interact
這是一段很是簡單的expect
示例代碼,演示了expect
的基本使用方法。code
#!/usr/tcl/bin/expect
:使用expect
來解釋該腳本;
set timeout 30
:設置超時時間,單位爲秒,默認狀況下是10秒;
set host "101.200.241.109"
:設置變量;
spawn ssh $username@$host
:spawn是進入expect環境後才能夠執行的expect內部命令,若是沒有裝expect或者直接在默認的SHELL下執行是找不到spawn命令的。它主要的功能是給ssh運行進程加個殼,用來傳遞交互指令;
expect "*password*"
:這裏的expect也是expect的一個內部命令,這個命令的意思是判斷上次輸出結果裏是否包含「password」的字符串,若是有則當即返回;不然就等待一段時間後返回,這裏等待時長就是前面設置的30秒;
send "$password\r"
:當匹配到對應的輸出結果時,就發送密碼到打開的ssh進程,執行交互動做;
interact
:執行完成後保持交互狀態,把控制權交給控制檯,這個時候就能夠手工操做了。若是沒有這一句登陸完成後會退出,而不是留在遠程終端上。進程
這就是對上述這段簡單簡單腳本的分析,在上述的示例中,涉及到expect
中一個很是重要的概念——模式-動做;即上述expect "*password*" {send "$password\r"}
這句代碼表達出來的含義。
結合着expect "*password*" {send "$password\r"}
這句代碼來講說「模式-動做」。簡單的說就是匹配到一個模式,就執行對應的動做;匹配到password字符串,就輸入密碼。你可能也會看到這樣的代碼:
expect { "password" { send "$password\r" exp_continue } eof { send "eof" } }
其中exp_continue
表示循環式匹配,一般匹配以後都會退出語句,但若是有exp_continue
則能夠不斷循環匹配,輸入多條命令,簡化寫法。
不少時候,咱們須要傳遞參數到腳本中,如今經過下面這段代碼來看看如何在expect
中使用參數:
#!/usr/tcl/bin/expect if {$argc < 3} { puts "Usage:cmd <host> <username> <password>" exit 1 } set timeout -1 set host [lindex $argv 0] set username [lindex $argv 1] set password [lindex $argv 2] spawn ssh $username@$host expect "*password*" {send "$password\r"} interact
在expect中,\$argc表示參數個數,而參數值存放在$argv中,好比取第一個參數就是[lindex $argv 0]
,以此類推。
可以在工做中熟練的使用Shell腳本就能夠很大程度的提升工做效率,若是再搭配上expect,那麼不少工做均可以自動化進行,對工做的展開如虎添翼。若是你會Python的話,你的視野將會更加開闊,那個時候你又會「嫌棄」expect了。
果凍想,認真玩技術的地方。
2016年2月17日 於呼和浩特。