Linux expect 用法

用法

1. [#!/usr/bin/expect]
這一行告訴操作系統腳本里的代碼使用那一個shell來執行。這裏的expect其實和Linux下的bash、windows下的cmd是一類東西。
注意:這一行需要在腳本的第一行。


2. [set timeout 30]
基本上認識英文的都知道這是設置超時時間的,現在你只要記住他的計時單位是:秒。timeout -1 爲永不超時,默認情況下,timeout是10秒;


3. [spawn ssh -l username 192.168.1.1]
spawn是進入expect環境後纔可以執行的expect內部命令,如果沒有裝expect或者直接在默認的SHELL下執行是找不到spawn命令的。所以不要用 “which spawn“之類的命令去找spawn命令。好比windows裏的dir就是一個內部命令,這個命令由shell自帶,你無法找到一個dir.com 或 dir.exe 的可執行文件。
它主要的功能是給ssh運行進程加個殼,用來傳遞交互指令。
spawn後面加上需要執行的shell命令,比如說spawn sudo touch testfile


4. [expect "password:"]
這裏的expect也是expect的一個內部命令,有點暈吧,expect的shell命令和內部命令是一樣的,但不是一個功能,習慣就好了。這個命令的意思是判斷上次輸出結果裏是否包含“password:”的字符串,如果有則立即返回,否則就等待一段時間後返回,這裏等待時長就是前面設置的30秒


5. [send "ispass\r"]
這裏就是執行交互動作,與手工輸入密碼的動作等效。
溫馨提示: 命令字符串結尾別忘記加上“\r”,如果出現異常等待的狀態可以覈查一下。


6. [interact]
執行完成後保持交互狀態,把控制權交給控制檯,這個時候就可以手工操作了。如果沒有這一句登錄完成後會退出,而不是留在遠程終端上。如果你只是登錄過去執行


7. $argv 參數數組
expect腳本可以接受從bash傳遞過來的參數.可以使用[lindex $argv n]獲得,n從0開始,分別表示第一個,第二個,第三個....參數
其中,$argc爲命令行參數的個數,$argv0爲腳本名字本身,$argv爲命令行參數。[lrange $argv 0 0]表示第1個參數,[lrange $argv 0 4]爲第一個到第五個參數。與C語言不一樣的地方在於,$argv不包含腳本名字本身。


8. send和send_user
send會將expect腳本中需要的信息發送給spawn啓動的那個進程,而send_user只是回顯用戶發出的信息,類似於shell中的echo而已。


9. 如果你在第一行(#!那行)使用-d (debug參數),可以在運行的時候輸出一些很有用的信息
比如你會看見
argv[0] = /usr/bin/expect argv[1] = -d argv[2] = ./launch.exp argv[3] = 1 argv[4] = 2 argv[5] = 3
使用這些也可以完成參數傳遞

10. exp_continue的用法

expect {
        -re "Permission denied, please try again." {
                send_user "Error:Permission denied.\n"
                exit
        }
        -re "Are you sure you want to continue connecting (yes/no)?" {
                send "yes\r";exp_continue
        }
        -re "assword:" {
                send "$loginpass\r";exp_continue
        }
        -re "Connection refused" {
                exit
        }
        timeout {
                exit
        }
        eof {
                exit
        }
}

使用exp_continue後,會重新從當前expect塊的開始重新執行,可以簡單理解問while循環的continue


四個命令



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"    //向進程輸入[email protected]\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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章