- 論壇徽章:
- 0
|
Expect 學(xué)習(xí)筆記
接觸Expect是迫不得已。系統(tǒng)管理員在工作中經(jīng)常會遇到這樣的問題,需要實現(xiàn)一個自動交互的工具,這個工具可以自動Telnet或者Ftp到指定的服務(wù)器上,成功login之后自動執(zhí)行一些命令來完成所需的工作。
當(dāng)然,有很多編程語言可以去解決此類問題,比如用C、Perl、或者Expect。
顯然,盡管C是無所不能的,但是解決此類問題還是比較困難,除非你熟悉Telnet或者Ftp協(xié)議。
曾經(jīng)見過別人用C實現(xiàn)了一個簡單的Telnet客戶端協(xié)議的程序,可以在這個程序加入自己的代碼來捕獲服務(wù)端的輸出,根據(jù)這些輸出來發(fā)送適當(dāng)?shù)闹噶顏磉M行遠(yuǎn)程控制。
使用Perl一樣可以實現(xiàn)這樣的功能,然而,Expect做的更出色,而且除支持Unix/Linux平臺外,它還支持Windows平臺,它就是為系統(tǒng)管理和軟件測試方面的自動交互類需求而產(chǎn)生的:
Expect是一個免費的編程工具語言,用來實現(xiàn)自動和交互式任務(wù)進行通信,而無需人的干預(yù)。
Expect的作者Don Libes在1990年開始編寫Expect時對Expect做有如下定義:
Expect是一個用來實現(xiàn)自動交互功能的軟件套件(Expect [is a] software suite for automating interactive tools)。
Expect語言是基于Tcl的, 作為一種腳本語言,Tcl具有簡單的語法:
cmd arg arg arg
一條Tcl命令由空格分割的單詞組成. 其中, 第一個單詞是命令名稱, 其余的是命令參數(shù) .
$foo
$符號代表變量的值. 在本例中, 變量名稱是foo.
[cmd arg]
方括號執(zhí)行了一個嵌套命令. 例如, 如果你想傳遞一個命令的結(jié)果作為另外一個命令的參數(shù), 那么你使用這個符號 .
"some stuff"
雙引號把詞組標(biāo)記為命令的一個參數(shù). "$"符號和方括號在雙引號內(nèi)仍被解釋 .
{some stuff}
大括號也把詞組標(biāo)記為命令的一個參數(shù). 但是, 其他符號在大括號內(nèi)不被解釋.
反斜線符號() 是用來引用特殊符號. 例如:n 代表換行. 反斜線符號也被用來關(guān)閉"$"符號 , 引號,方括號和大括號的特殊含義 .
最好的學(xué)習(xí)方法就是邊干邊學(xué),對于已經(jīng)熟悉一種編程語言的人來說,用另一種新的語言來寫程序解決問題,是很容易的事。所以大概了解一下基本語法后,就一邊動手解決問題,一邊查手冊吧。
關(guān)于Tcl和Expect的語法,請參考Unix/Linux 平臺任務(wù)的自動化相關(guān)部分。
例1:下面是一個telnet到指定的遠(yuǎn)程機器上自動執(zhí)行命令的Expect腳本,該腳本運行時的輸出如下:
# /usr/bin/expect sample_login.exp root 111111
spawn telnet 10.13.32.30 7001
Trying 10.13.32.30...
Connected to 10.13.32.30.
Escape character is '^]'.
accho console login: root
Password:
Last login: Sat Nov 13 17:01:37 on console
Sun Microsystems Inc. SunOS 5.9 May 2004
#
Login Successfully...
# uname -p
sparc
# ifconfig -a
lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1
inet 127.0.0.1 netmask ff000000
eri0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2
inet 10.13.22.23 netmask ffffff00 broadcast 10.13.22.255
ether 0:3:ba:4e:4a:aa
# exit
accho console login:
Finished...
下面是該腳本的源代碼:
# vi sample_login.exp:
proc do_console_login {login pass} {
set timeout 5
set done 1
set timeout_case 0
while ($done) {
expect {
"console login:" { send "$loginn" }
"Password:" { send "$passn" }
"#" {
set done 0
send_user "nnLogin Successfully...nn"
}
timeout {
switch -- $timeout_case {
0 { send "n" }
1 {
send_user "Send a return...n"
send "n"
}
2 {
puts stderr "Login time out...n"
exit 1
}
}
incr timeout_case
}
}
}
}
proc do_exec_cmd {} {
set timeout 5
send "n"
expect "#"
send "uname -pn"
expect "#"
send "ifconfig -an"
expect "#"
send "exitn"
expect "login:"
send_user "nnFinished...nn"
}
if {$argc<2} {
puts stderr "Usage: $argv0 login passwaord.n "
exit 1
}
set LOGIN [lindex $argv 0]
set PASS [lindex $argv 1]
spawn telnet 10.13.32.30 7001
do_console_login $LOGIN $PASS
do_exec_cmd
close
exit 0
上面的腳本只是一個示例,實際工作中,只需要重新實現(xiàn)do_exec_cmd函數(shù)就可以解決類似問題了。
在例1中,還可以學(xué)習(xí)到以下Tcl的語法:
1. 命令行參數(shù)
$argc,$argv 0,$argv 1 ... $argv n
if {$argc<2} {
puts stderr "Usage: $argv0 login passwaord.n "
exit 1
}
2. 輸入輸出
puts stderr "Usage: $argv0 login passwaord.n "
3. 嵌套命令
set LOGIN [lindex $argv 0]
set PASS [lindex $argv 1]
4. 命令調(diào)用
spawn telnet 10.13.32.30 7001
5. 函數(shù)定義和調(diào)用
proc do_console_login {login pass} {
..............
}
6. 變量賦值
set done 1
7. 循環(huán)
while ($done) {
................
}
8. 條件分支Switch
switch -- $timeout_case {
0 {
...............
}
1 {
...............
}
2 {
...............
}
}
9. 運算
incr timeout_case
此外,還可以看到 Expect的以下命令:
send
expect
send_user
可以通過-d參數(shù)調(diào)試Expect腳本:
# /usr/bin/expect -d sample_login.exp root 111111
[ 本帖最后由 mocou 于 2005-12-31 10:55 編輯 ] |
評分
-
查看全部評分
|