編輯:開發入門
簡介: Expect 是進行高效的系統和網絡管理工作不可或缺的一種工具,不過很多人對它存在著一定的誤解。在本文中,將通過一些常見的用例來介紹 Expect 所提供的優點。
如果您從事系統和網絡管理工作,那麼您將需要 Expect。
更准確地說,您為什麼不使用 Expect 呢?對於一些常見的任務,它可以節省大量的時間。盡管您現在可能已經在使用 Expect,但是您可能並不是很清楚下面所描述的一些功能。
Expect 可以實現命令行交互的自動化
要從 Expect 中獲益,您並不需要掌握有關它的所有內容;讓我們從一個具體的示例開始,研究 Expect 如何在 AIX® 或者其他操作系統中簡化您的工作:
假設您在一些 UNIX® 或者類 UNIX 主機上具有登錄帳號,並且您需要更改這些帳號的密碼,但是並沒有使用網絡信息服務(Network Information Service,NIS)、輕量級目錄訪問協議(Lightweight Directory Access Protocol,LDAP)或者能夠在每台計算機上識別出您是相同的登錄用戶的一些其他機制對這些帳號進行同步。在大多數情況下,登錄到一台特定的主機,並運行合適的 passwd
命令並不會花費很長的時間,可能只需要一分鐘而已。但是因為無法將您的密碼編寫在腳本中,所以您必須 進行“手動”登錄,是這樣嗎?
其實並不是這樣的。事實上,標准 Expect 分發版(完整的分發版)中包括一種命令行工具(以及描述其使用的手冊頁面!),該工具恰好可以負責完成這項煩瑣的工作。passmass
(請參見參考資料)是使用 Expect 編寫的一個簡短的腳本,它可以使得在二十台計算機上進行密碼更改的工作就像在一台計算機上進行密碼更改那樣簡單。不需要反復地輸入相同的密碼,您可以只啟動一次 passmass
,並允許您的桌面計算機負責更新每個單獨的主機。您節省了大量時間並可以稍事休息,同時對於已經輸入過的內容,極大地降低了錯誤輸入的可能性。
Expect 的限制
這個 passmass
應用程序是一個非常優秀的模型,它說明了 Expect 的許多常規特性:
passmass
了。但實際情況並不總是這樣的,而 Expect 非常適合於處理各種各樣現有的問題。也許 Expect 能夠幫助您節省更多的時間,以便您能夠使您的配置更加合理化,這樣一來您就不再需要 Expect 了。在此期間,您可以充分地利用它。passmass
僅使用 telnet
、rlogin
或者 slogin
進行登錄。我希望當前所有的 developerWorks 讀者都不再使用這些協議,而是使用 ssh
,passmasss
並沒有 對 ssh 提供全面的支持。passmass
進行增強,以支持 ssh
和其他選項。您可能已經了解了足夠多的內容,完全可以開始編寫或者修改您自己的 Expect 工具。當然,實際上 passmass
分發版中包含了以 ssh
方式進行登錄的代碼,但是省略了相應的命令行解析以到達這部分代碼。本文介紹了一種方法,您可以修改分發版源代碼,對 ssh
與telnet
以及其他協議進行同樣的處理:
清單 1. 經過修改的、接受 -ssh 參數的 passmass 片段
... } "-rlogin" { set login "rlogin" continue } "-slogin" { set login "slogin" continue } "-ssh" { set login "ssh" continue } "-telnet" { set login "telnet" continue ...
在我自己的代碼中,我實際上從這個“樣本”中提出了更多的內容。現在,passmass
第 100 行附近的這一連串測試,非常好地說明了 Expect 的可讀性。這裡並沒有涉及到很深的編程技術,不需要面向對象、單體應用程序、協同例程,或者其他巧妙的技術。您只是請求計算機負責您通常進行的輸入工作。恰好,這個簡單的操作步驟可以節省大量時間和精力。
什麼是 Expect?
Expect 究竟是 什麼,您應該如何使用它呢?
“Expect”涉及到一些獨特的概念,許多經常使用 Expect 的用戶對這些概念並不是十分清楚:
expect
命令是其中的一個命令,Expect 以此對 Tcl 進行了擴展。請注意,考慮到一些技術細節超出了本文的關注重點,在前面的描述中,我稍微有些歪曲事實;例如,常規的 Expect 可執行程序不僅擴展了 Tcl 命令集,它還可以識別啟動時的一些額外的命令行參數。盡管這些內容並不是專門針對主要的主題:一個簡短的 Expect 程序所能夠為系統管理員完成的工作,超出了大多數人的預期。
在了解了這個背景信息之後,“passmass
是一個 Expect 應用程序”表示:
passmass
是一個以 Expect 語言編寫的文本文件。passmass
的主機上執行 expect passmass ...
,那麼您將得到正確的 passmass
功能。請注意,具體的執行方法可能有一些變種:可以在一個 Tcl 解釋器中以交互的方式加載 Expect、運行 passmass
、創建 passmass
作為一個獨立的可執行程序,等等。同樣地,這些替代方法超出了本文所關注的重點。
網絡管理示例
讓我們考慮一項更大的挑戰,網絡操作中心的日常操作中一項更典型的操作:檢索一組托管的 Cisco 交換機的當前配置信息。盡管有些站點使用 SNMP 或者 HTTP 來進行這些操作,但是更常見的是使用控制台或者頻內 telnet
會話來獲取該信息。許多管理員認為,完成這項工作唯一可行的方法是輸入與清單 2 中所示類似的命令。
清單 2. 典型的“手工”配置自檢
telnet $MY_ROUTER [User: admin] [passWord: ...] CCNA01# show running-config [... Current configuration: ... version 12.0 ... FIFTY LINES MORE OF CONFIGURATION DETAIL ... End]
其實並不是這樣的;實際上,通過在 cron
、回復郵件(mailback)服務器,或者類似的作業控制機制(請參見清單 3)中進行調用,這項工作完全可以實現自動化。
清單 3. 配置自檢的自動化
#!/usr/bin/expect # initialize host, password, ... package require Expect set prompt {[00m# } spawn telnet $host expect {User: } send admin\r expect password: send $passWord\r expect -exact $prompt send "show running-config\r" expect -exact $prompt send exit\r
這個腳本可以自動地檢索路由器的配置信息,即在正確地編寫了腳本之後,對其進行監視時不再需要輸入密碼或者進行干預。
一些常見的混淆
這個示例是典型的 Expect 使用情況,其中有幾點值得注意。首先,不存在任何適用於各種情況的解決方案。許多管理員在獲得 Expect 時都認為它是一個單獨使用的工具,以解決他們當前所碰到的問題。那不是 Expect。Expect 與電子鐵釘尋找器 (electronic stud finder) 不同,後者可以不依靠任何其他工具、獨立地查找鐵釘。Expect 更像是一個手鑽:您必須將其與合適的鑽頭,或者轉換接頭、孔鋸,或者其他附件進行組合,才能真正實現它的用途。
同樣地,Expect 至少需要進行一些自定義工作。當然,我通常使用 Expect 來解決一些其他工具所無法輕松解決的問題。running-config
的案例說明了,只需要幾行內容,Expect 就可以自動地獲得大量的信息。即使是這個簡單的示例,也呈現出 Expect 所帶來的一些問題。例如,這種特定的自動化,需要將管理密碼以明文的形式嵌入到 Expect 腳本中;您需要判斷,它是否適合於您的具體環境。
這個案例至少在一些更多的方面是非常典型的。$prompt
讓我感到有些奇怪。屏幕上所顯示的是 CCNA01#
;對於許多設備來說,這是非常典型的,這個提示符實際上嵌入了一些不可見的控制字符。幸運的是,Expect 提供了各種有價值的調試開關,以報告其交互過程;這正是我確定 CCNA01 所生成的各種字符的方法。
另外,如前所述,清單 3 返回了整個會話,包括我所需要的配置報告,還加上登錄和退出作為其開始和結束。隱含在一般請求中的另一個有關 Expect 的常見誤解是“檢索一個命令的值”。Expect 並沒有提供這些語義。當您坐在鍵盤前並輸入一個命令時,您將它的操作認為是在下一個提示符之前所看到的相關顯示。對於網絡互連協議(如 telnet
),在結果和提示符之間實際上並沒有什麼區別;您可以作為一個觀察者對這些內容的含義進行分析。
與這種網絡通信模型完全一致,Expect 並不直接區分結果和提示符。所有的 Expect 都稱為對話,即它通過 send
發送的字符序列,以及它所期望(expect
)的內容。因此在實際中,我使用一個正則表達式解析來為我提供所需要的細節信息。Expect 的擴展正則表達式功能非常強大,並且很容易通過代碼確定格式。現在,讓我們重點關注通常無法通過腳本實現自動化的廣泛主題。
並發
請記住,Expect 是一種功能強大的、通用的語言。實際的 Expect 應用程序通常用於解析命令行參數、將結果顯示在分欄的表格中、從數據庫中檢索歷史數據、顯示圖形用戶界面 (GUI),以及更多的用途。所有這些都是常規的計算工作,本文中的示例並沒有展示這些方面的內容。文本的重點是正確地理解 Expect 獨特的價值。
使用與清單 3 中所示類似的解決方案,網絡管理員通常會考慮下一步的“水平方向的”增強:從大量類似的計算機檢索這類報告。Expect 提供了循環構造 foreach
、while
等等,從而使得這樣的工作變得更加簡單。
它也可能很快地變得無法接受。假設您負責上百台 LAN 主機,這是一個比較常見的情況。您使用一個 Expect 腳本自動地依次登錄到這些計算機,並檢索重要的數據。現在,您對該腳本稍微進行一下抽象,以便對整個集合進行遍歷。
問題是,運行所得到的腳本可能會花費很長的時間。它登錄到一台主機,請求結果,接收結果,注銷,然後轉向下一台主機,請求一個新的結果,等等。這個過程中的延遲使得人們希望能夠使用某種方法一次性地請求所有的結果,並按照結果到達的順序對其進行收集,導致這些結果不同順序的原因包括網絡滯後、不同的負載,以及其他延遲。
有一種方法可以實現這種操作。實際上,Expect 提供了一些非常好的功能來同時管理多個對話。本文提供了一個程序的示例,該程序多次進行登錄,在每個登錄上執行一些長時間運行的命令,然後根據結果到達的順序進行接收;對這個案例進行了整理,以便這些結果返回的順序與其啟動順序相反(請參見清單 4)。
清單 4. 並發檢索來自多個登錄的報告
#!/home/claird/local/ActiveTcl/bin/tclsh package require Expect log_user 0 # Initialize user, passphrase, ... here. # Sequentially login and issue time-consuming commands to all # hosts. for {set i 0; set delay 8} {$delay > 0} {incr i; incr delay -1} { spawn ssh $user@$host set sid($i) $spawn_id expect rsa': send $passphrase expect "Last login" expect -ex $prompt set active($sid($i)) $i send -i $sid($i) "echo `date`; sleep $delay; echo `date`; echo \ '$delay done on $i.'\r" } while {[llength [array names active]]} { expect -i [array names active] -ex $prompt { puts "RECEIVED: $::expect_out(buffer)" send -i $expect_out(spawn_id) exit\r expect -i $expect_out(spawn_id) eof unset active($expect_out(spawn_id)) } }
當您運行這個腳本時,將看到與清單 5 所示類似的結果。
清單 5. 運行清單 4 所得到的結果
RECEIVED: echo `date`; sleep 1; echo `date`; echo '1 done on 7.' Mon Apr 23 22:15:15 UTC 2007 Mon Apr 23 22:15:16 UTC 2007 1 done on 7. RECEIVED: echo `date`; sleep 2; echo `date`; echo '2 done on 6.' Mon Apr 23 22:15:15 UTC 2007 Mon Apr 23 22:15:17 UTC 2007 2 done on 6. RECEIVED: echo `date`; sleep 3; echo `date`; echo '3 done on 5.' Mon Apr 23 22:15:15 UTC 2007 Mon Apr 23 22:15:18 UTC 2007 3 done on 5. ... RECEIVED: echo `date`; sleep 8; echo `date`; echo '8 done on 0.' Mon Apr 23 22:15:14 UTC 2007 Mon Apr 23 22:15:22 UTC 2007 8 done on 0.
在編程的層次上,請注意,所有這些登錄都是通過基於密碼的 ssh
登錄到相同的主機,並使用相同的用戶和密碼憑據。在一個更實際的示例中,可以通過更多行的代碼來管理各個不同的主機,對每個主機使用不同的帳號和登錄協議。盡管對於那些對網絡管理員非常有 價值的命令,sleep
是一個很好的模型;但是沒有理由先睡眠數秒鐘,然後再返回。
即使這個示例,也無法盡述 Expect 的所有功能。Expect 還提供了使用一個內置的套接字編程接口,直接管理 TCP/IP 對話的功能,並且它可以實現半自動化,在兩種不同的模式之間來回切換,用戶在其中一種模式中輸入部分對話,而 Expect 在另一種模式中實現所有操作的自動化。
我們將在以後的文章中介紹這些主題。本文的目標是,展示 Expect 中包含了大多數管理員並不知道的許多內容,具體來說是了解了該工具後,馬上就能夠解決網絡管理工作中各種常見的問題。在腳本中使用密碼和密碼條目,以及並發地控制多個連接,這些功能都是非常強大的。
總結
Expect 可以完成所有看起來無法實現自動化的工作:在腳本中使用密碼條目、登錄到遠程用戶的會話和返回對他或者她的控制,以及更多的工作。盡管它已經得到了廣泛使用,但是 Expect 卻常常被人們所誤解。正確地理解有關 Expect 的一些基本知識(如何調用它、它的對話模型、它的編程輔助,等等),以便在系統和網絡管理工作中更充分地發揮它的作用。
簡介黑莓和 iPhone 都提供了受歡迎的、高容量的移動平台,但是卻分別針對兩個不同的消費群體。黑莓是企業業務用戶的不二選擇。但是,作為一種消費設備,它在易用性和 “新
簡介本文建立在 “使用 Eclipse 開發 android 應用程序” 一文的基礎之上,探究了 Android 的網絡功能。了解如何利用 Android 的網絡選項來
連接 JavaScript 接口下一步是啟用 Activity 中的 Java 代碼,以與 WebVIEw 管理的 Html 文件中的 JavaScript 代碼交互。
公共交通減少了交通擁擠和由此產生的污染。同時還降低了用戶的壓力水平和需要支付的費用。現在許多 Web 站點和移動應用程序幫助全球各個城市的乘客,購物者和游客成為合乎道德