linux expect詳解(ssh自動登入)

懶惰的肥兔發表於2015-02-24

shell指令碼實現ssh自動登入遠端伺服器示例:

#!/usr/bin/expect
spawn ssh root@192.168.22.194
expect "*password:"
send "123\r"
expect "*#"
interact

 

原文連結:http://www.xuanhao360.com/linux-expects/

Expect是一個用來處理互動的命令。藉助Expect,我們可以將互動過程寫在一個指令碼上,使之自動化完成。形象的說,ssh登入,ftp登入等都符合互動的定義。下文我們首先提出一個問題,然後介紹基礎知四個命令,最後提出解決方法。

問題

如何從機器A上ssh到機器B上,然後執行機器B上的命令?如何使之自動化完成?


四個命令

Expect中最關鍵的四個命令是send,expect,spawn,interact。

send:用於向程式傳送字串
expect:從程式接收字串
spawn:啟動新的程式
interact:允許使用者互動

1. send命令

send命令接收一個字串引數,並將該引數傳送到程式。

expect1.1> send "hello world\n"
hello world

2. expect命令


(1)基礎知識

expect命令和send命令正好相反,expect通常是用來等待一個程式的反饋。expect可以接收一個字串引數,也可以接收正規表示式引數。和上文的send命令結合,現在我們可以看一個最簡單的互動式的例子:

expect "hi\n"
send "hello there!\n"

這兩行程式碼的意思是:從標準輸入中等到hi和換行鍵後,向標準輸出輸出hello there。

tips: $expect_out(buffer)儲存了所有對expect的輸入,<$expect_out(0,string)>儲存了匹配到expect引數的輸入。

比如如下程式:

expect "hi\n"
send "you typed <$expect_out(buffer)>"
send "but I only expected <$expect_out(0,string)>"

當在標準輸入中輸入

test
hi

是,執行結果如下

you typed: test
hi
I only expect: hi

(2)模式-動作

expect最常用的語法是來自tcl語言的模式-動作。這種語法極其靈活,下面我們就各種語法分別說明。

單一分支模式語法:

expect "hi" {send "You said hi"}

匹配到hi後,會輸出"you said hi"

多分支模式語法:

expect "hi" { send "You said hi\n" } \
"hello" { send "Hello yourself\n" } \
"bye" { send "That was unexpected\n" }

匹配到hi,hello,bye任意一個字串時,執行相應的輸出。等同於如下寫法:

expect {
"hi" { send "You said hi\n"}
"hello" { send "Hello yourself\n"}
"bye" { send "That was unexpected\n"}
}

3. spawn命令

上文的所有demo都是和標準輸入輸出進行互動,但是我們跟希望他可以和某一個程式進行互動。spawm命令就是用來啟動新的程式的。spawn後的send和expect命令都是和spawn開啟的程式進行互動的。結合上文的send和expect命令我們可以看一下更復雜的程式段了。

set timeout -1
spawn ftp ftp.test.com      //開啟新的程式,該程式使用者連線遠端ftp伺服器
expect "Name"             //程式返回Name時
send "user\r"        //向程式輸入anonymous\r
expect "Password:"        //程式返回Password:時
send "123456\r"    //向程式輸入don@libes.com\r
expect "ftp> "            //程式返回ftp>時
send "binary\r"           //向程式輸入binary\r
expect "ftp> "            //程式返回ftp>時
send "get test.tar.gz\r"  //向程式輸入get test.tar.gz\r

這段程式碼的作用是登入到ftp伺服器ftp ftp.uu.net上,並以二進位制的方式下載伺服器上的檔案test.tar.gz。程式中有詳細的註釋。


4.interact

到現在為止,我們已經可以結合spawn、expect、send自動化的完成很多工了。但是,如何讓人在適當的時候干預這個過程了。比如下載完ftp檔案時,仍然可以停留在ftp命令列狀態,以便手動的執行後續命令。interact可以達到這些目的。下面的demo在自動登入ftp後,允許使用者互動。

spawn ftp ftp.test.com
expect "Name"
send "user\r"
expect "Password:"
send "123456\r"
interact

解決方法

上文中提到:

如何從機器A上ssh到機器B上,然後執行機器B上的命令?如何使之自動化完成?

下面一段指令碼實現了從機器A登入到機器B,然後執行機器B上的pwd命令,並停留在B機器上,等待使用者互動。具體含義請參考上文。

#!/home/tools/bin/64/expect -f
 set timeout -1  
 spawn ssh $BUser@$BHost
 expect  "*password:" { send "$password\r" }
 expect  "$*" { send "pwd\r" }
 interact

 

相關文章