首頁  >  文章  >  運維  >  Linux expect詳解

Linux expect詳解

藏色散人
藏色散人轉載
2019-08-09 14:22:549481瀏覽

Linux expect詳解

隨處可見的expect

#第一次見expect這個指令還是我第一次參加全量上線的時候,那是公司的一個牛人用Shell腳本寫的一套自動部署、MD5 比對、發布的全量上線工具,沒事的時候,看了下其中的幾個腳本,好多的expect指令。實在看不懂這個expect指令的用法,所以就找時間總結了這篇關於expect指令的文章。

推薦:【Linux影片教學

先拋出一個問題

現在有兩台Linux主機A和B,如何從A主機ssh到B主機,然後在B主機上執行指令,如何讓這個過程全程自動化?你可能會使用這種方法:

ssh admin@10.220.20.15 "ls"

但是這種方式比較笨拙,每次都要輸入密碼,同時並不能執行一些複雜的邏輯或指令。那麼如何實現全程自動化呢?這就要用到今天這篇文章總結的expect了。

expect是什麼?

expect是一個免費的程式設計工具,用來實現自動的互動式任務,而無需人為幹預。說穿了,expect就是一套用來實現自動互動功能的軟體。

在實際工作中,當我們執行命令、腳本或程式時,這些命令、腳本或程式都需要從終端機輸入某些繼續運行的指令,而這些輸入都需要人為的手動進行。而利用expect,則可以根據程序的提示,模擬標準輸入提供給程序,從而實現自動化交互執行。這就是expect! ! !

expect基礎

在使用expect時,基本上都是和以下四個指令打交道:

Linux expect詳解

#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的基本使用方法。

#!/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了。

以上是Linux expect詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:jellythink.com。如有侵權,請聯絡admin@php.cn刪除