Expect 學(xué)習(xí)筆記 收藏
原貼:
[u]Expect 學(xué)習(xí)筆記 [/u]
接觸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(jìn)行遠(yuǎn)程控制。
使用Perl一樣可以實現(xiàn)這樣的功能,然而,Expect做的更出色,而且除支持Unix/Linux平臺外,它還支持Windows平臺,它就是為系統(tǒng)管理和軟件測試方面的自動交互類需求而產(chǎn)生的:
Expect是一個免費的編程工具語言,用來實現(xiàn)自動和交互式任務(wù)進(jìn)行通信,而無需人的干預(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 編輯 ]
--------------------------------------------------------------------------------
very_99 回復(fù)于:2005-11-02 09:30:18
EXPECT
交互式程序可編程對話,第5版
expect [ -dDinN ] [ -c cmds ] [ -[f|b] ] cmdfile ] [ args ]'F}
簡介
Expect是一種能利用腳本和其它交互式程序進(jìn)行對話的程序。通過腳本,expect能夠獲知一個程序應(yīng)該有怎樣的響應(yīng)和怎樣是正確的響應(yīng)。它采用翻譯式語言來控制流結(jié)構(gòu)和高層結(jié)構(gòu)使對話進(jìn)行下去。而且,還允許用戶在想要控制的時候能夠直接控制程序,然后再將控制交回給腳本。
Expectk是expect和tk的混合體,它可以象expect和tk那樣使用。同樣,expect也能夠被C和C++直接調(diào)用(沒有Tcl存在的情況下)。可以參看libexpect(3)。
Expect這個名字來源于廣泛使用的uucp, Kermit和其它的modem控制程序等的send/expect序列的思想,但是它并不象uucp那樣,expect對環(huán)境沒有很特殊的要求,因此可以作為用戶級的命令和任何程序交互,而且expect實際上可以同時和多個程序交互。
舉例來說,expect可以做這些事情:
使你的計算機可以回?fù)?,這樣你就不必為你的上網(wǎng)而支付電話費啦。
一遍遍的開始一個游戲程序(如rogue),直到那個隨機產(chǎn)生的裝備設(shè)置達(dá)到最好,然后把控制交給你來玩游戲。
運行fsck,對它的提問按預(yù)先設(shè)置的標(biāo)準(zhǔn)給出響應(yīng)“yes”,“no”或者將控制交給你。
連到另外一個網(wǎng)絡(luò)或BBS(如MCI Mail, CompuServe),自動收下你的信件,就好象原來發(fā)到你的本地系統(tǒng)一樣。
攜帶rlogin, telnet, tip, su, chgrp等需要的環(huán)境變量,當(dāng)前目錄或其它信息
用普通腳本來執(zhí)行一個任務(wù)存在著很多種理由使得是不可行的,(如果你試試就知道了)但用expect就都成為可能了。
總地說來,expect在運行那些需要在程序和用戶之間進(jìn)行交互的程序時是很有用的。交互一旦被程序化地指定了,運行起來會很方便。如果需要,Expect也可以將控制交還給用戶(不停止正在運行的程序)。類似的,用戶也可以在任何時間把控制交還給腳本。|
注:老外可真夠羅嗦的,就這么簡單的意思,讓我翻譯這么半天,還是我來簡單說說吧?:expect是個腳本解釋程序,就好象/bin/sh,/bin/ksh一樣。所完成的功能呢,最簡單的就是自動對需要人工交互和程序進(jìn)行自動交互,比如一個程序需要你不斷地輸入yes繼續(xù),你懶得做,干脆用寫個expect腳本自動輸入yes就行了。當(dāng)然,expect可以做的事情遠(yuǎn)不止這些,它實際上是tcl(Tool Command Language)的一個變種,格式和tcl程序也類似,寫expect腳本對懂tcl的人應(yīng)該不難。用過secureCRT的人應(yīng)該知道有個自動登錄的設(shè)置,那就是利用expect實現(xiàn)的。好了,我不羅嗦了,繼續(xù)干活。
引用:用法
expect從cmdfile中讀取命令列表來執(zhí)行,同樣它也可以在有執(zhí)行權(quán)限的腳本的第一行中加上#!標(biāo)識來隱式地執(zhí)行,如:
#!/usr/local/bin/expect -f
當(dāng)然,路徑應(yīng)該準(zhǔn)確地描述expect的位置,/usr/local/bin只是一個例子。
-c參數(shù)指示其后的命令在腳本的最先開始執(zhí)行,命令應(yīng)該用引號引起來以不被shell打散。這個選項可被多次使用。多個命令如果用一個-c指示,則應(yīng)用分號分隔。命令將按其書寫順序執(zhí)行。(使用expectk時,這個參數(shù)用作-command)
-d參數(shù)允許一些診斷輸出,報告主要的expect和交互命令行為。在expect腳本開始用exp_internal 1也可以起到一樣的作用,-d會多打出expect的版本。(strace命令在跟蹤狀態(tài)時很有用,trace命令在跟蹤變量時很有用)(expectk中此參數(shù)為-diag)。
-D參數(shù)打開交互debugger,后跟一個整數(shù)。如果這個整數(shù)是非零,或者^C被按下(或者碰到一個設(shè)置的斷點,或者腳本中設(shè)置的其它合適的debugger命令)Debugger會在下一個tcl過程之前控制程序。關(guān)于debugger的信息參看README或SEE ALSO。(expectk中此參數(shù)為-Debug)
-f參數(shù)指定從哪個文件中讀取命令。當(dāng)被用在#!指示(見上)中時此參數(shù)是可選的,所以其它參數(shù)可在命令行中提供。(expectk中為-file)。
-b參數(shù)。缺省地,命令文件被整個地讀到內(nèi)存中執(zhí)行,但是有時需要一行行地讀取,比如,標(biāo)準(zhǔn)輸入stdin就是這樣。為了強制特定的文件被這樣讀入,可以使用-b參數(shù)。(expectk中為-buffer)。如果文件名是“-”,則表示從標(biāo)準(zhǔn)輸入stdin讀入。(用“./-”來表示一個叫作“-”的文件)
-i參數(shù)使expect交互地提示輸入命令,而不是從文件中讀命令。命令提示行通過exit命令或一個eof字符結(jié)束。參看interpreter(見下)。-i假設(shè)既沒有命令文件,又沒有使用-c參數(shù)。(expectk中為-interactive)。
--用來對選項參數(shù)結(jié)束的劃界。在你想傳遞一個象選項參數(shù)樣的參數(shù)給你的腳本時,這個選項是很有用的,它使得expect不對其進(jìn)行翻譯。也可以放在#!行來阻止expect對任何選項參數(shù)格式的參數(shù)的翻譯。比如,下面例子將保留原始參數(shù)(包括腳本名)到argv中:
#!/usr/local/bin/expect 注意加參數(shù)到#!行時應(yīng)該遵守getopt(3)和execve(2)的慣例。
-N選項。 $exp_library/expect.rc文件如果存在的話將被自動的啟用,除非-N選項被使用。(expectk中為-NORC)這樣的話就會自動找~/.expect.rc,除非加了-n參數(shù)。如果定義了環(huán)境變量DOTDIR,那就會從那里找.expect.rc。(expectk中為-norc)。expect.rc的使用只在執(zhí)行完-c參數(shù)指定的命令后。
-v打印expect的版本號并退出。(expectk中為-version)
可選的args被結(jié)構(gòu)化成一個列表存在argv中,argc被初始化成argv的長度。
Argv0被定義為腳本的名字。下面例子打印出腳本名和前三個參數(shù):
send_user "$argv0 [lrange $argv 0 2]
[ 本帖最后由 mocou 于 2005-12-31 10:57 編輯 ]
--------------------------------------------------------------------------------
very_99 回復(fù)于:2005-11-02 09:32:48
% set i 1
1
字符串應(yīng)該用引號括起來:
% set str "test"
'test'
要輸出一個標(biāo)量的內(nèi)容,使用put語句:
% puts $str
test
$用來說明str是一個變量。puts函數(shù)在標(biāo)準(zhǔn)輸出顯示變量的內(nèi)容。
數(shù)組也可以用set語句定義,實際上,tcl中建立數(shù)組只是單個建立數(shù)組的元素。例如
,
% set arr(1) 0
0
% set arr(2) 1
1
這樣就建立了一個兩個元素的數(shù)組arr。在TCL中,不存在相當(dāng)于數(shù)組邊界這樣的東西
,例如
% set arr(100) to
to
這時數(shù)組中實際只存在arr(1),arr(2)和arr(100),這是和C語言不同的地方。用arr
ay size命令可以返回數(shù)組的大?。?
% array size arr
3
訪問數(shù)組的方法和訪問標(biāo)兩實際是一樣的,例如:
% puts $arr(100)
to
可以用同樣的方法創(chuàng)建多維數(shù)組。
要使用數(shù)組中的所有元素,需要使用一種特殊的便利方式。首先要啟動startsearsh:
% array startsearch arr
s-1-arr
這里返回了一個搜索id,你可以把它傳遞給某個變量,因為以后還要使用它進(jìn)行進(jìn)一
步的搜索:
% set my_id [array startsearch arr]
s-1-arr
現(xiàn)在my_id的內(nèi)容是s-1-arr,然后,就可以搜索arr的內(nèi)容了:
% array nextelement arr $my_id
whi
這里的array nextelement返回的是什么?可能有點出乎你的意料,是arr數(shù)組的下標(biāo)
,再執(zhí)行一次array nextelement命令又會找出另外一個下標(biāo):
% array nextelement arr $my_id
4
這樣遍歷下去,可以找出arr數(shù)組的所有下標(biāo),而知道下標(biāo)之后,就可以用$arr(4)之
類的方式訪問arr的內(nèi)容了。當(dāng)遍歷完成之后,array nextelement命令將簡單地返回:
% array nextelement arr $my_id
%
這時就可以停止遍歷過程了,如果你想確認(rèn)遍歷是否完成,可以使用array anymore命
令:
% array anymore arr $my_id
0
返回0說明遍歷已經(jīng)完成。
串處理
TCL中可以進(jìn)行一般的串處理過程,這可以使用string命令和append命令,append命令
將某個字符串加到另外一個字符串的后面:
% set str1 "test "
test
% set str2 "cook it"
cook it
% append str1 $str2 " and other"
test cook it and other
string命令可以執(zhí)行字符串的比較,刪除和查詢,其格式是 string [參數(shù)] string1
[string2]
參數(shù)可以是下面的命令之一:
compare 按照字典順序?qū)ψ址M(jìn)行比較,根據(jù)相對關(guān)系返回-1,0或者+1。
first 返回string2中第一次出現(xiàn)string1的位置,如果失敗,返回-1。
last 返回string2中最后一次出現(xiàn)string1的位置,如果失敗,返回-1
trim 從string1中刪除開頭和結(jié)尾的出現(xiàn)在string2中的字符
trimleft 從string1中刪除開頭的出現(xiàn)在string2中的字符。
trimright 從string1中刪除結(jié)尾的出現(xiàn)在string2中的字符
下面幾個用在string中的參數(shù)不需要string2變量:
length 返回tring1的長度
tolower 返回將string1全部小寫化的串
toupper 返回將string1全部大寫化的串
運算
TCL的運算方式比較別扭,它使用expr命令作為計算符號,其用法類似C語言的+=和/=
,例如,
% set j [expr $i/5]
1
注意TCL會自動選擇整數(shù)或者浮點計算:
% set l [ expr $i /4.0]
1.25
% set l [ expr $i /4]
1
在TCL里面可以使用+ - * /和%作為基本運算符,另外通常還包括一些數(shù)學(xué)函數(shù),如a
bs,sin,cos,exp和power(乘方)等等。
另外,還有一個起運算符作用的命令incr,它用來對變量加一:
% set i 1
1
% incr i
2
流程控制
tcl支持分支和循環(huán)。分支語句可以使用if和switch實現(xiàn)。if語句的和C語言類似,如
if { $ x < 0 } {
set y 10;
}
注意判斷子句也需要使用花括號。
與C語言一樣,tcl的if語句也可以使用else和elseif。
switch語句的用法有點類似這樣:
switch $x {
0 { set y 10;}
10 { set y 100;}
20 { set y 400;}
}
與C的switch語句不同,每次只有符合分支值的子句才被執(zhí)行。
循環(huán)命令主要由for,foreach和while構(gòu)成,而且每一個都可以使用break和continue
子句。
for語句的格式有點類似這樣:
for { set i 0} {$i < 10} { incr i} {puts $i}
將會輸出從1到9的整數(shù)。
如果用while循環(huán),這個句子可以寫成
while {$i < 10 } {
puts $i;
incr i;
}
foreach是對于集合中的每一個元素執(zhí)行一次命令,大致的命令格式是
foreach [變量] { 集合 } {
語句;
}
例如
% foreach j { 1 3 5} {
put $j;
}
1
3
5
函數(shù)
如同在一般的編程語言里面一樣,在tcl里面也可以定義函數(shù),這是通過proc命令實現(xiàn)
的:
proc my_proc {i}{
puts $i;
}
這樣就定義了一個名字叫proc的函數(shù),它只是在終端顯示輸入變元的內(nèi)容。
要使用這個函數(shù),簡單地輸入它的名字:
% my_proc { 5 }
5
如果變元的數(shù)目是0,只要使用空的變元列表,例如 proc my_proc {} {語句;}
盡管tcl還可以處理更復(fù)雜的過程,但是我們不再介紹了,例如文件的讀寫以及tk圖形
語言,因為我們處理tcl的主要目標(biāo)就是理解expect,對于更復(fù)雜的編程工作,我們建議
你使用perl。
11.1.2 expect
expect是建立在tcl基礎(chǔ)上的一個工具,它用來讓一些需要交互的任務(wù)自動化地完成。
我們首先從一個簡單的例子開始,如同在這一節(jié)一開始就提到的,我們想設(shè)置一個自動
的文件下載程序。
我們看一看這樣的一個例子腳本:
#! /usr/bin/expect
spawn ftp 202.199.248.11
expect "Name"
send "ftpr"
expect "Password:"
send "nothingr"
expect "apply"
send "cd /pub/UNIX/Linux/remoteXr"
expect "successful."
send "binr"
expect "set to I"
send "get exceed5.zipr"
expect "complete."
send "quitr"
這個是什么意思?呵呵,就是個自動下載程序。第一行說明這個程序應(yīng)該調(diào)用/usr/b
in/expect去執(zhí)行,然后的就是expect命令。
察看expect的手冊頁面(man expect)可以得到一個很長的expect說明,可惜其中關(guān)于
expect的語法仍然介紹的不夠。一般來說,expect主要用在需要自動執(zhí)行人機交互的過
程中,例如fsck程序,這個程序會不斷地提問"yes/no",像這樣的命令就可以用expect
來完成。
spawn語句在expect腳本中用于啟動一個新的進(jìn)程,在我們的程序中,spawn ftp 202
.199.248.11就是去執(zhí)行ftp程序,接下來,就是expect和send的指令對了。
每一對expect和send指令代表一個信息/回應(yīng)。如果這樣說不好理解的話,那么可以看
一看ftp的具體執(zhí)行過程:
ftp 202.199.248.11
Connected to 202.199.248.11.
220 mail.asnc.edu.cn FTP server (BeroFTPD 1.3.3(3) Sun Feb 20 15:52:49 CST
2000.
Name (202.199.248.11:wanghy):
顯然,一旦連接成功,服務(wù)器會返回一個Name(202.199.248.11:wanghy):的字符串來
要求客戶給出用戶名。expect語句簡單地在返回信息中查詢你給出的字符串,一旦成功
就執(zhí)行下面的命令,現(xiàn)在,expect " Name"已經(jīng)成功地找到了Name字符串,接下來可以
執(zhí)行send命令了。
send命令比expect命令更簡單,它簡單地向標(biāo)準(zhǔn)輸入提交你設(shè)定的字符串,現(xiàn)在設(shè)置
為send "ftpr"表示等到登錄信息之后就給出一個輸入ftp回車,也就是標(biāo)準(zhǔn)的登錄過
程。
下面的行與這些行完全一樣,只是機械地等待服務(wù)器的回應(yīng),并且提交自己的輸入。
要使用這個expect腳本,你只需要將它設(shè)置為可執(zhí)行的屬性,然后執(zhí)行它,expect就
會執(zhí)行你需要的服務(wù)。
由于expect是tcl的擴展,所以你在expect文件中可以象tcl腳本一樣設(shè)置變量和程序
流程。
現(xiàn)在我們看一看我們還能夠如何改進(jìn)我們的expect腳本。ftp命令可能會失敗,比如遠(yuǎn)
端的機器可能會無法提供服務(wù),或者在啟動ftp命令時本地機器發(fā)生問題。為了處理這一
類的問題,我們可以使用expect的timeout選項來設(shè)置超時的話expect腳本自動退出:
#! /usr/bin/expect
spawn ftp 202.199.248.11
expect {
timeout exit
Connect
}
………………
注意這里面使用的花括號。它的含義是使用一組并列表達(dá)式。使用并列表達(dá)式的主要
原因是這樣:如果使用下面的指令對:
expect timeout
exit
那么由于expect腳本是順序執(zhí)行的,那么當(dāng)程序執(zhí)行到這個expect的時候就會阻塞,
所以程序會一直等待到timeout然后退出。并列表達(dá)式則是相當(dāng)于switch的行為,只要列
出的幾項內(nèi)容有一項得到滿足,expect命令就得到滿足,于是程序可以正常執(zhí)行。上面
的腳本表示,如果連接ftp的時候發(fā)生了超時,那么就退出,否則,一旦發(fā)現(xiàn)Connect應(yīng)
答,說明服務(wù)器已經(jīng)正常了,那么就可以繼續(xù)運行了。
我們可以看看用tcl能夠?qū)ξ覀兊膃xpect腳本提供什么幫助。我們可以設(shè)置讓expect腳
本不斷地連接遠(yuǎn)端服務(wù)器的服務(wù),直到正常建立連接開始,為此,我們可以把建立連接
的命令放在一個循環(huán)里面,并且根據(jù)回應(yīng)的不同自動選擇重新輸入命令還是繼續(xù)執(zhí)行:
spawn ftp
while {1} {
expect "ftp>"
send "o 202.199.248.11r"
expect {
"Connected" break
"refused" { sleep 10} ;
}
}
這里使用了我們在tcl語言中講到的while和break命令,熟悉C的讀者應(yīng)該很容易看出
它的行為:不斷地等待ftp>提示符,在提示符下面發(fā)送連接遠(yuǎn)端服務(wù)器的命令,如果服
務(wù)器回應(yīng)是refused(連接失?。?,就等待10秒鐘,然后開始下一次循環(huán);如果是Conne
cted,那么就跳出循環(huán)執(zhí)行下面的命令。sleep是expect的一個標(biāo)準(zhǔn)命令,表示暫停若干
秒鐘。
expect還支持許多更復(fù)雜的進(jìn)程控制方式,如fork,disconnect等等,你可以從手冊
頁面中得到詳細(xì)的信息。另外,各種tcl運算符和流程控制命令,包括tcl函數(shù)也可以使
用。
有些讀者可能會問,如果expect執(zhí)行的話是否控制臺輸入不能使用了,答案是否定的
。expect命令運行時,如果某個等待的信息沒有得到,那么程序會阻塞在相應(yīng)的expect
語句處,這時,你在鍵盤上輸入的東西仍然可以正常地傳遞到程序中去,其實對于那些
expect處理的信息,原則上你輸入的內(nèi)容仍然有效,只是expect的反映太快,總是搶在
你的前面“輸入”就是了。知道了這一點之后,你就可能寫一個expect腳本,讓expect
自動處理來自fscki的那些惡心的yes/no選項(我們介紹過,這些yes/no其實完全是多余
的,正常情況下你除了選擇yes之外什么也干不了)。
缺省下,expect在標(biāo)準(zhǔn)輸出(你的終端上)輸出所有來自應(yīng)用程序的回應(yīng)信息,你可
以用下面的兩個命令重定向這些信息:
log_file [文件名]
這個命令讓expect在你設(shè)置的文件中記錄輸出信息。必須注意,這個選項并不影響控
制臺輸出信息,不過如果你通過crond設(shè)置expect腳本在半夜運行的話,你就確實可能需
要這個命令來記錄各種信息了。例如:
log_file expect.log
log_user 0/1
這個選項設(shè)置是否顯示輸出信息,設(shè)置為1時是缺省值,為0 的話,expect將不產(chǎn)生任
何輸出信息,或者說簡單地過濾掉控制臺輸出。必須記住,如果你用log_user 0關(guān)閉了
控制臺輸出,那么你同時也就關(guān)閉了對記錄文件的輸出。
這一點很讓人困擾,如果你確實想要記錄expect的輸出卻不想讓它在控制臺上制造垃
圾的話,你可以簡單地把expect的輸出重定向到/dev/null:
./test.exp > /dev/null
你可以象下面這樣使用一對fork和disconnect命令。expect的disconnect命令將使得
相應(yīng)的進(jìn)程到后臺執(zhí)行,輸入和輸出被重定向到/dev/null:
if [fork]!=0 exit
disconnect
fork命令會產(chǎn)生出一個子進(jìn)程,而且它產(chǎn)生返回值,如果返回的是0,說明這是一個子
進(jìn)程,如果不為0,那么是父進(jìn)程。因此,執(zhí)行了fork命令之后,父進(jìn)程死亡而子進(jìn)程被
disconnect命令放到后臺執(zhí)行。注意disconnect命令只能對子進(jìn)程使用。