Expect

Expect是Unix系統中用來進行自動化控制和測試的軟件工具，由Don Libes製作，作為Tcl腳本語言的一個擴展，應用在交互式軟件中如telnet，ftp，Passwd，fsck，rlogin，tip，ssh等等。該工具利用Unix偽終端包裝其子進程，允許任意程序通過終端接入進行自動化控制；也可利用Tk工具，將交互程序包裝在X11的圖形用戶界面中。

**基本介紹**
Expect含有利用正則表達式進行模式匹配以及通用的編程功能，允許簡單的腳本智能地管理如下工具：telnet,ftp和ssh（這些工具都缺少編程的功能），宏以及其它程序。Expect腳本的出現使得這些老的軟件工具有了新的功能和更多的靈活性。

**例子**
一個簡單的腳本程序例子就能實現自動的telnet會話：
# 假定 $remote_server, $my_user_id, $my_password, 和$my_command 已經讀入。
# 向遠程服務器請求打開一個telnet會話，並等待服務器詢問用戶名
spawn telnet $remote_server
expect "username:"
# 輸入用戶名，並等待服務器詢問密碼
send "$my_user_id\r"
expect "password:"
# 輸入密碼，並等待鍵入需要運行的命令
send "$my_password\r"
expect "%"
# 輸入預先定好的密碼，等待運行結果
send "$my_command\r"
expect "%"
# 將運行結果存入到變量中，顯示出來或者寫到磁盤中
set results $expect_out(buffer)
# 退出telnet會話，等待服務器的退出提示EOF
send "exit\r"
expect eof
另一個腳本程序例子，自動建立FTP會話
# 向遠程服務器請求打開一個FTP會話，並等待服務器詢問用戶名
spawn ftp $remote_server
expect "username:"
# 輸入用戶名，並等待服務器詢問密碼
send "$my_user_id\r"
expect "password:"
# 輸入密碼，並等待FTP提示符的出現
send "$my_password\r"
expect "ftp>"
# 切換到二進制模式，並等待FTP提示符的出現
send "bin\r"
expect "ftp>"
# 關閉ftp的提示符
send "prompt\r"
expect "ftp>"
# 下載所有文件
send "mget *\r"
expect "ftp>"
# 退出此次ftp會話，並等待服務器的退出提示EOF
send "bye\r"
expect eof

**用法說明**
Expect是一種將現有的實用程序組合起來的膠合劑，通常考慮的是如何使Expect利用系統現有的工具解決問題而不是如何在Expect中解決問題。
Expect主要應用涉及商用軟件產品。很多這類的產品都會提供某種命令行工具，但這些工具缺乏腳本編程的能力，只是為了幫助用戶管理產品，而商家通常不會在如何實現一個穩定性好的腳本語言上耗費很多精力。Expect腳本中可以包含shell，查詢環境變量，通過執行某些Unix命令獲得更多的信息，然後在產品所帶命令行接口中加入必須的信息，來完成用戶的目標。在產品命令行接口中查詢相關信息，該腳本可以在多種選擇中智能地決定當前應該做什麼比較合適。
每次Expect操作完成，運行結果將保存在本地環境變量 $expect_out 中。這允許腳本收集這些信息給用戶以相應的反饋，同時也允許根據當前情況發送相對應的指令。
Expect通常用來建立一組測試套件，可以用在程序、組件或者嵌入式系統中。DejaGnu就是利用Expect寫成的一組測試套件。它被大量地應用於測試 gcc，對於遠程目標的測試例如嵌入式開發也是非常合適的。
你可以利用一種叫作"autoexpect"的工具，自動生成expect腳本。這個工具觀測你的操作，並利用啟發性知識生成expect腳本。儘管生成的代碼可能會很長，含義上有點模糊，你可以修改生成的腳本使它成為你需要的代碼。

**觀點**

**利**
Expect可通過cron封裝系統管理任務，在規定的時期運行。能夠這樣做是因為Expect僅僅使用已經安裝在主機中的系統管理工具，不需要學習額外的工具。如果程序員學過Tcl，那麼轉移到Expect是一件非常簡單的工作，相同的編程結構和語法，再加上一些內置的額外功能。
業界對室內管理任務使用Expect提供了很大的支持。Expect在很多的公司廣泛使用，例如Silicon Graphics, IBM, HP, Sun, Xerox, Amdahl, Tektronix, AT&T, ComputerVision和世界銀行，利用Expect對開發項目、文件傳輸、帳號管理、網絡測試進行室內自動測試。
Expect已經以多種模塊的方式移植到Python和Perl語言中。Expect命令的部分子集移植到Java和嵌入到SwichTermJ（基於Java的終端仿真器）之中。這些例行程序通常是原程序的同等功能的另一種解釋方式。一旦你理解了其中的概念，如果需要的話，換到其它語言，也就很容易了。

**弊**
Expect繼承了Tcl的語法規範，對於使用其它腳本語言的人來說這是相當陌生的。和其它語言如bash、csh和Perl相比，Expect的語法模式是不同的。就像有時候一個變量的前綴冠以"$"，有時候又不需要。有些版本的Expect和Perl、Python語言的語法倒是很相似的。
另一個缺陷是在不同的平臺移植Expect腳本很難。例如，一個Expect腳本使用基於Unix的工具，就不可能適合移植到Windows平臺。如果可能的話，程序員必須找到相應的命令行程序，能夠提供相同的信息，這就可能需要修改expect腳本的send部分，而這部分恰恰就是整個腳本的核心。如果你使用的是tcl,perl或者python這些獨立於平臺的工具，使用它們各自的POSIX接口訪問文件、對遠端交互進行標準的POSIX處理（telnet,ftp等等），就不會出現上述問題。
一個不明顯的缺陷是，有時Expect可能並不是解決問題的最好方法。例如，一個系統管理員需要登錄到多個服務器，這些自動的操作要使用Expect就得配以保存的密碼，而不是更安全的解決方案採用ssh代理密鑰。雖然這種自動交互工具很吸引人，但是還是有很多其它的辦法可以更安全穩定地解決同樣的問題。
Expect自動化控制命令行工具，但是對圖形用戶界面就失效了。Windows提供了不少有價值的工具，很多是基於圖形用戶界面的，這就是Expect失效的地方了。Windows下圖形界面程序可以通過像Autohotkey或者AutoIt等工具來實現自動化控制。

**參考文獻**

**進一步閱讀**

**外部引用**
 Expect on SourceForge (current)date=20081223024525 - Official homepage (very outdated!)- The Tcler's Wiki -- Expect pagedate=20090123050508 - Perl Expect.pm moduledate=20090107084342 - Pexpect a Pure Python Expect-like moduledate=20140820062632 - Expect Scripting Tutorial- Empty - expectlike tool to run command-line interactive programs in UNIX shell-scriptsdate=20200409020937 - Expect-lite -- a wrapper for expect, making automation easy, quick, and fundate=20090104060903 - Bulletproof: Reliable CLI interface using Expect- ExpectJ - a Java implementation of the Unix expect utilitydate=20090104063248