By francis_hao May 31,2017
本文翻譯了部分Expect的man手冊,只選取了個人常用的功能,因此並不完善。
Expect是一個可以和交互式程序對話的程序
概述
介紹
通過腳本,Expect可以知道應該從對話程序中期望得到什么,和應該回應什么。它支持多分支結構,並且用戶可以在需要的時候取得控制權,並在之后將控制權交還給腳本。
Expect也可以被直接用在c或c++中,詳見libexpect(3)。
Expect可以做的事情:telnet、ftp、ssh和scp等等(如果不在意用戶名和密碼信息)
用法
Expect從cmdfile(-f選項指定)中讀取一系列的命令去執行。但一般更常用的方式是將文件作為可執行腳本,在文件第一行添加如下類似的標識,以告知shell通過Expect解析本文件。
#!/usr/bin/expect
選項 |
說明 |
-c |
可執行命令的前置符,其后的命令應該被引起來,該選項可以使用多次,每個-c可以跟多個以分號分隔的命令。命令按照出現的順序執行,例如: expect -c "puts first\n; puts second" -c "puts three" |
-d |
輸出一些診斷信息,命令執行時的內部動作。當你寫的腳本和預期不符時,可用此項來調試腳本 |
-D |
交互式的調試器,類似gdb。適合專業人士使用 |
-f |
指定Expect讀取的文件,如果文件是-,則表示是從標准輸入讀取。該選項會將文件一次性全部讀入內存,該選項是可選的 |
-b |
類似-f選項,只是每次只讀取一行 |
-i |
以交互的方式運行expect,等效直接敲expect |
-- |
可以用來界定選項的結束,此項可以用在當你想傳遞一個類似選項的參數時,防止Expect誤認為是選項 |
-N/-n |
如果$exp_library/expect.rc和~/.expect.rc存在,Expect會分別自動讀取,若要阻止此過程則需要分別指定-N和-n。此項一般用不上。 |
-v |
輸出版本號並退出 |
可選項args的內容以列表的形式被保存在argv中,argc被初始化為argv的長度(個數),argv0保存腳本的名字。
命令
Expect使用Tcl的語法,又進行了一些擴展,比如spawn、send、expect和interact等。常用的擴展命令如下,按常用度排序
最好的介紹Expect和Tcl的資料是《Exploring Expect》這本書。本man手冊雖然包含示例但十分有限,畢竟man手冊主要作為參考資料。
在本文中Expect指Expect程序,expect指Expect程序中的expect命令。
spawn
spawn [args] program [args]
創建一個新的進程運行program [args]。program的標准輸入、標准輸出和標准錯誤都連接到Expect,這樣程序就可以被Expect讀寫了。當Expect執行close命令或者進程關閉了任何文件標識符時,連接會斷開。
當以spawn啟動一個進程時,進程描述符被賦給變量spawn_id,它表示了當前進程,spawn_id可被讀寫,以實現任務控制。
正常情況下,spawn只花費很少的時間,如果spawn耗費了大量的時間,可能是由於pty的問題,此時可以通過-d選項顯示執行過程。
選項 |
說明 |
-noecho |
默認情況下,spawn會回顯命令名和參數。此選項可以取消回顯。 |
-ignore |
指定在spawned process種要忽略的信號。 |
expect
expect [[-opts] pat1 body1] ... [-opts] patn [bodyn]
等待,直到模式patn匹配到spawn打開的進程的輸出,超過指定的時間,或遇到EOF。
如果模式關鍵字是eof,那么對應的執行體是處理遇到文件結尾的
如果模式關鍵字是timeout,那么對應的執行體是處理超時的,如果沒有指明timeout,則默認不會做任何動作。默認的超時時間是10秒,但是可以通過如下命令重設
set timeout 30
如果設置為-1,則意味着無限等待。
如果模式關鍵字是default,那么對應的執行體會處理超時或文件結尾。
每次新的輸出到達時,會按順序比較每個模式,如果模式匹配到了,那么對應的執行體會被執行。如果有多個模式匹配,只執行第一個出現的。
下面的例子,看起來像一個可以成功登陸的腳本片段。
expect { |
字串中可以使用^匹配起始串,用$匹配結尾串。
如果模式關鍵詞是null,那么僅當匹配到一個單個ascii字符"0"時才會執行后面的執行體。沒有可用的辦法來匹配0字節數據,不論是通過全匹配還是正則匹配。
在獲得匹配后,程序的所有輸出字串,截至匹配字串,被保存在變量expect_out(buffer)中,多至九個匹配子串分別被保存在變量expect_out(1,string)至expect_out(9,string)中。
選項 |
說明 |
-gl |
保護以"-"開始的模式不被認為是選項 |
-re |
正則表達式,在單項前面指定 |
-ex |
匹配確切的字串,不對*、^和$等特殊字符進行翻譯 |
-nocase |
不區分大小寫 |
-timeout |
設置當前expect的超時時間,而不是使用變量timeout的時間 |
exp_continue
exp_continue [-continue_timer]
允許expect繼續執行自身而不是往下執行,默認情況下,exp_continue會重置timeout,如果不想重置timeout,使用-continue_timer選項。
expect_user
expect_user [expect_args]
類似expect,不過是從標准輸入讀取字符,行必須以回車結尾,以使expect能識別它們。
send
send [-flags] string
發送string到當前進程,例如:
send "hello world\r"
就是發送h e l l o <blank> w o r l d <return>到當前進程,
字符會立即被發送,盡管那些行緩沖的程序只會在有回車鍵時才讀取,回車鍵用'\r'表示。因此,下面的示例和上面示例等同。
send "hello "
send "world\r"
選項 |
說明 |
-- |
其后的參數被強制解釋成字串,而不是選項。 |
-i |
選項說明字串發送給spawn_id。 |
-s\-h |
慢的輸入\類人的輸入方式,可以提供輸入的間隔設置。具體參見man手冊 |
send_error
send_error [-flags] string
類似send,不過輸出發送到標准錯誤,而不是當前進程
send_log
send_log [--] string
類似send,不過string只發送到log文件。(see log_file)
send_tty
send_tty [-flags] string
類似send,不過輸出發送到/dev/tty而不是當前進程。
send_user
send_user [-flags] string
類似send,不過輸出發送到標准輸出,而不是當前進程。
interact
interact [string1 body1] ... [stringn [bodyn]]
將當前進程的控制權交付給用戶。
string-body對可以作為參數,以使當有string輸入時,執行body。下面的示例看上去是一個可運行片段。
interact { |
輸入的字符會按string列出的順序進行匹配,當有部分匹配時,當前輸入的字符不會被發送到當前進程,只有當后續輸入的字符不能使之匹配時才會發送,若匹配則執行body。以上例為例,在輸入"abc"的過程中,進程不會回顯這些字符,如果輸入"abq",則只有在輸入到"q"時,"abq"才會同時被回顯。
選項 |
說明 |
-ex |
防止以"-"開頭的模式被翻譯成選項 |
-re |
用正則匹配的模式翻譯string,此選項下匹配的子串被保存在變量interact_out中。類似expect的expect_out。 |
-echo |
回顯每一個字符,即使這個字符會被匹配中 |
當模式是eof時,表示遇到文件結尾的行為,默認是"return"。
當模式是timeout時(需指定超時時間),表示在指定時間沒有輸入時的行為,此項沒有默認的超時時間,變量timeout的值在此無效。
當模式是null時,僅當匹配到一個單個ascii字符"0"時才會執行后面的執行體。沒有可用的辦法來匹配0字節數據,不論是通過全匹配和正則匹配。
interact中的return使interact返回到它的調用。而inter_return使interact的調用執行return。
sleep
sleep seconds
腳本進入睡眠模式,睡眠時間單位為秒
close
close [-slave] [-onexec 0|1] [-i spawn_id]
關閉連接到當前進程的連接
選項 |
說明 |
-i |
指定關閉名為spawn_id的進程 |
-onexec |
檢測是否有新打開的進程或進程是否有重疊,若有, 0:保持打開,1:強制關閉 |
-slave |
關閉spawn_id關聯的子進程 |
exit
Expec退出

本文由 劉英皓 創作,采用 知識共享 署名-非商業性使用-相同方式共享 3.0 中國大陸 許可協議進行許可。歡迎轉載,請注明出處:
轉載自:http://www.cnblogs.com/yinghao1991/p/6926125.html
參考
【1】man expect
