天天看點

expect vs shell

最近調試程式,由于測試資料集過大,程式要跑幾天幾夜, 還好,測試集有一定的獨立性,這就使我有空子鑽了---把程式分到多台機子上運作,再把資料重定向到本機上,嘿嘿。

  這樣搞過一次,用了8台機子,運作了10個多小時,還是偷偷的ssh到别人的機子上運作的---不要說我rp不好,反正晚上嘛,我偷偷的用一下也沒什麼影響:)

  不過,其實發現這樣其實還是很麻煩的, 要分别ssh 上去,還要手工計算配置設定資料段,重定向。。。etc。。總之用的機子越多越麻煩,還容易出錯。。

  于是乎,自然想到寫段 shell script 解決,不過很遺憾的發現,shell的話 ssh上去就停在那裡的,其實也不奇怪,shell 為了安全起見,對程式提供了最小限度的控制(想啟動的程式發送消息等),而把所有的互動都留給了使用者, 也就是說shell基本不能運作互動式的程式了---比如那些執行期間要你輸入選擇的程式。。

我這樣的需求,那用shell跟不用差不多了----到互動的時候都是要自己手動敲指令的。。

   當然不甘心了, google之,發現有個專門幹這個事的東西: expect  ---以前從來沒聽過這個 :)

“ Expect是一個免費的程式設計工具語言,用來實作自動和互動式任務進行通信,而無需人的幹預”, 粗略看了下文法,感覺我的問題可以很輕易的解決,試了一下,果不其然^_^, expect真是個好東西。。

貼下我的expect script :

      1 #! /usr/bin/expect

      2 proc process { name disk step } {

      3 spawn ssh $name

      4 expect "*:)*"

      5 puts "ssh $name ok"

      6 send " cd **some dir** /n "

      7 expect "*:)*"

      8 puts "cd ok"

      9 append file "data_" $disk "_" $step

     10 puts $file

     11 append param1 "--disk=" $disk

     12 append param2 "--step=" $step

     13 send " ./moon $param1 $param2  > $file & /n"

     14 expect "*:)*"

     15 puts " run moon ok"

     16 send " exit /n"

     17 expect "*:)*"

     18 puts "exit ok"

     19 }

     20

     21 set step [ expr 140000/$argc +1 ]

     22 set disk 0

     23 for { set i 0 } { $i < $argc } { incr i } {

     24 puts $i

     25 set name [ lindex $argv $i ]

     26 puts $name

     27

     28 process $name $disk $step

     29

     30 set $disk [ expr $disk+$step ]

     31 }

     32

     33 puts "done. :)"

============================

附:網上看到的一些expect 有關的資料(我感覺比較好的):

===============================

 Expect是一個免費的程式設計工具語言,用來實作自動和互動式任務進行通信,而無需人的幹預。

  Expect的作者Don Libes在1990年開始編寫Expect時對Expect做有如下定義:

  Expect是一個用來實作自動互動功能的軟體套件(Expect [is a] software suite for automating interactive tools)。

引用:  Expect語言是基于Tcl的, 作為一種腳本語言,Tcl具有簡單的文法:       

                cmd arg arg arg  

                一條Tcl指令由空格分割的單詞組成. 其中, 第一個單詞是指令名稱, 其餘的是指令參數 .  

                $foo  

                $符号代表變量的值. 在本例中, 變量名稱是foo.  

                [cmd arg]  

                方括号執行了一個嵌套指令. 例如, 如果你想傳遞一個指令的結果作為另外一個指令的參數, 那麼你使用這個符号 . 

                "some stuff"  

                雙引号把詞組标記為指令的一個參數. "$"符号和方括号在雙引号内仍被解釋 .  

                {some stuff}  

                大括号也把詞組标記為指令的一個參數. 但是, 其他符号在大括号内不被解釋.  

                反斜線符号() 是用來引用特殊符号. 例如:n 代表換行. 反斜線符号也被用來關閉"$"符号 , 引号,方括号和大括号的特殊含義 . 

  最好的學習方法就是邊幹邊學,對于已經熟悉一種程式設計語言的人來說,用另一種新的語言來寫程式解決問題,是很容易的事。是以大概了解一下基本文法後,就一邊動手解決問題,一邊查手冊吧。

  關于Tcl和Expect的文法,請參考Unix/Linux 平台任務的自動化相關部分。

引用:  例1:下面是一個telnet到指定的遠端機器上自動執行指令的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

  上面的腳本隻是一個示例,實際工作中,隻需要重新實作do_exec_cmd函數就可以解決類似問題了。

引用:  在例1中,還可以學習到以下Tcl的文法:

        1. 指令行參數

            $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. 指令調用         

            spawn telnet 10.13.32.30  7001 

        5. 函數定義和調用

             proc do_console_login {login pass} { 

                    ..............             

             }

        6. 變量指派

             set done 1

        7. 循環

             while ($done) {

                   ................

             }

        8. 條件分支Switch

             switch -- $timeout_case {

                    0 {

                       ...............

                    }

                    1 {

                       ...............               

                    }

                    2 {

                       ...............           

                    }

              }

        9. 運算

             incr timeout_case

        此外,還可以看到 Expect的以下指令:

        send

        expect

        send_user

        可以通過-d參數調試Expect腳本:

        # /usr/bin/expect -d sample_login.exp root 111111

EXPECT

互動式程式可程式設計對話,第5版

expect [ -dDinN ] [ -c cmds ] [ -[f|b] ] cmdfile ] [  args  ]'F}

簡介

Expect是一種能利用腳本和其它互動式程式進行對話的程式。通過腳本,expect能夠獲知一個程式應該有怎樣的響應和怎樣是正确的響應。它采用翻譯式語言來控制流結構和高層結構使對話進行下去。而且,還允許使用者在想要控制的時候能夠直接控制程式,然後再将控制交回給腳本。

Expectk是expect和tk的混合體,它可以象expect和tk那樣使用。同樣,expect也能夠被C和C++直接調用(沒有Tcl存在的情況下)。可以參看libexpect(3)。

Expect這個名字來源于廣泛使用的uucp, Kermit和其它的modem控制程式等的send/expect序列的思想,但是它并不象 uucp那樣,expect對環境沒有很特殊的要求,是以可以作為使用者級的指令和任何程式互動,而且expect實際上可以同時和多個程式互動。

舉例來說,expect可以做這些事情:

使你的計算機可以回撥,這樣你就不必為你的上網而支付電話費啦。

一遍遍的開始一個遊戲程式(如rogue),直到那個随機産生的裝備設定達到最好,然後把控制交給你來玩遊戲。

運作fsck,對它的提問按預先設定的标準給出響應“yes”,“no”或者将控制交給你。

連到另外一個網絡或BBS(如MCI Mail, CompuServe),自動收下你的信件,就好象原來發到你的本地系統一樣。

攜帶rlogin, telnet, tip, su, chgrp等需要的環境變量,目前目錄或其它資訊

用普通腳本來執行一個任務存在着很多種理由使得是不可行的,(如果你試試就知道了)但用expect就都成為可能了。

總地說來,expect在運作那些需要在程式和使用者之間進行互動的程式時是很有用的。互動一旦被程式化地指定了,運作起來會很友善。如果需要,Expect也可以将控制交還給使用者(不停止正在運作的程式)。類似的,使用者也可以在任何時間把控制交還給腳本。|

注:老外可真夠羅嗦的,就這麼簡單的意思,讓我翻譯這麼半天,還是我來簡單說說吧?:expect是個腳本解釋程式,就好象/bin/sh, /bin/ksh一樣。所完成的功能呢,最簡單的就是自動對需要人工互動和程式進行自動互動,比如一個程式需要你不斷地輸入yes繼續,你懶得做,幹脆用寫個expect腳本自動輸入yes就行了。當然,expect可以做的事情遠不止這些,它實際上是tcl (Tool Command Language)的一個變種,格式和tcl程式也類似,寫expect腳本對懂tcl的人應該不難。用過 secureCRT的人應該知道有個自動登入的設定,那就是利用expect實作的。好了,我不羅嗦了,繼續幹活。

引用:用法

expect從cmdfile中讀取指令清單來執行,同樣它也可以在有執行權限的腳本的第一行中加上#!辨別來隐式地執行,如:

#!/usr/local/bin/expect -f

當然,路徑應該準确地描述expect的位置,/usr/local/bin隻是一個例子。

-c參數訓示其後的指令在腳本的最先開始執行,指令應該用引号引起來以不被shell打散。這個選項可被多次使用。多個指令如果用一個-c訓示,則應用分号分隔。指令将按其書寫順序執行。(使用expectk時,這個參數用作-command)

-d參數允許一些診斷輸出,報告主要的expect和互動指令行為。在expect腳本開始用exp_internal 1也可以起到一樣的作用,-d會多打出expect的版本。(strace指令在跟蹤狀态時很有用,trace指令在跟蹤變量時很有用)(expectk中此參數為- diag)。

 

-D參數打開互動debugger,後跟一個整數。如果這個整數是非零,或者^C被按下(或者碰到一個設定的斷點,或者腳本中設定的其它合适的 debugger指令)Debugger會在下一個tcl過程之前控制程式。關于debugger的資訊參看README或SEE ALSO。 (expectk中此參數為-Debug)

-f參數指定從哪個檔案中讀取指令。當被用在#!訓示(見上)中時此參數是可選的,是以其它參數可在指令行中提供。(expectk中為-file)。

-b參數。預設地,指令檔案被整個地讀到記憶體中執行,但是有時需要一行行地讀取,比如,标準輸入stdin就是這樣。為了強制特定的檔案被這樣讀入,可以使用-b參數。(expectk中為-buffer)。如果檔案名是“-”,則表示從标準輸入stdin讀入。(用“./-”來表示一個叫作 “-”的檔案)

-i參數使expect互動地提示輸入指令,而不是從檔案中讀指令。指令提示行通過exit指令或一個eof字元結束。參看interpreter(見下)。-i假設既沒有指令檔案,又沒有使用-c參數。(expectk中為-interactive)。

--用來對選項參數結束的劃界。在你想傳遞一個象選項參數樣的參數給你的腳本時,這個選項是很有用的,它使得expect不對其進行翻譯。也可以放在#!行來阻止expect對任何選項參數格式的參數的翻譯。比如,下面例子将保留原始參數(包括腳本名)到argv中:

#!/usr/local/bin/expect 注意加參數到#!行時應該遵守getopt(3)和execve(2)的慣例。

-N選項。 $exp_library/expect.rc檔案如果存在的話将被自動的啟用,除非-N選項被使用。(expectk中為- NORC)這樣的話就會自動找~/.expect.rc,除非加了-n參數。如果定義了環境變量DOTDIR,那就會從那裡找.expect.rc。 (expectk中為-norc)。expect.rc的使用隻在執行完-c參數指定的指令後。

-v列印expect的版本号并退出。(expectk中為-version)

可選的args被結構化成一個清單存在argv中,argc被初始化成argv的長度。

Argv0被定義為腳本的名字。下面例子列印出腳本名和前三個參數:

send_user "$argv0 [lrange $argv 0 2]

% set i 1 

字元串應該用引号括起來: 

% set str "test" 

'test' 

要輸出一個标量的内容,使用put語句: 

% puts $str 

test 

$用來說明str是一個變量。puts函數在标準輸出顯示變量的内容。 

數組也可以用set語句定義,實際上,tcl中建立數組隻是單個建立數組的元素。例如 

, 

% set arr(1) 0 

% set arr(2) 1 

這樣就建立了一個兩個元素的數組arr。在TCL中,不存在相當于數組邊界這樣的東西 

,例如 

% set arr(100) to 

to 

這時數組中實際隻存在arr(1),arr(2)和arr(100),這是和C語言不同的地方。用arr 

ay size指令可以傳回數組的大小: 

% array size arr 

通路數組的方法和通路标兩實際是一樣的,例如: 

% puts $arr(100) 

to 

可以用同樣的方法建立多元數組。 

要使用數組中的所有元素,需要使用一種特殊的便利方式。首先要啟動startsearsh: 

% array startsearch arr 

s-1-arr 

這裡傳回了一個搜尋id,你可以把它傳遞給某個變量,因為以後還要使用它進行進一 

步的搜尋: 

% set my_id [array startsearch arr] 

s-1-arr 

現在my_id的内容是s-1-arr,然後,就可以搜尋arr的内容了: 

% array nextelement arr $my_id 

whi 

這裡的array nextelement傳回的是什麼?可能有點出乎你的意料,是arr數組的下标 

,再執行一次array nextelement指令又會找出另外一個下标: 

% array nextelement arr $my_id 

這樣周遊下去,可以找出arr數組的所有下标,而知道下标之後,就可以用$arr(4)之 

類的方式通路arr的内容了。當周遊完成之後,array nextelement指令将簡單地傳回: 

% array nextelement arr $my_id 

這時就可以停止周遊過程了,如果你想确認周遊是否完成,可以使用array anymore命 

令: 

% array anymore arr $my_id 

傳回0說明周遊已經完成。 

串處理 

TCL中可以進行一般的串處理過程,這可以使用string指令和append指令,append指令 

将某個字元串加到另外一個字元串的後面: 

% set str1 "test " 

test 

% set str2 "cook it" 

cook it 

% append str1 $str2 " and other" 

test cook it and other 

string指令可以執行字元串的比較,删除和查詢,其格式是 string [參數] string1 

[string2] 

參數可以是下面的指令之一: 

compare 按照字典順序對字元串進行比較,根據相對關系傳回-1,0或者+1。 

first 傳回string2中第一次出現string1的位置,如果失敗,傳回-1。 

last 傳回string2中最後一次出現string1的位置,如果失敗,傳回-1 

trim 從string1中删除開頭和結尾的出現在string2中的字元 

trimleft 從string1中删除開頭的出現在string2中的字元。 

trimright 從string1中删除結尾的出現在string2中的字元 

下面幾個用在string中的參數不需要string2變量: 

length 傳回tring1的長度 

tolower 傳回将string1全部小寫化的串 

toupper 傳回将string1全部大寫化的串 

運算 

TCL的運算方式比較别扭,它使用expr指令作為計算符号,其用法類似C語言的+=和/= 

,例如, 

% set j [expr $i/5] 

注意TCL會自動選擇整數或者浮點計算: 

% set l [ expr $i /4.0] 

1.25 

% set l [ expr $i /4] 

在TCL裡面可以使用+ - * /和%作為基本運算符,另外通常還包括一些數學函數,如a 

bs,sin,cos,exp和power(乘方)等等。 

另外,還有一個起運算符作用的指令incr,它用來對變量加一: 

% set i 1 

% incr i 

流程控制 

tcl支援分支和循環。分支語句可以使用if和switch實作。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語句不同,每次隻有符合分支值的子句才被執行。 

循環指令主要由for,foreach和while構成,而且每一個都可以使用break和continue 

子句。 

for語句的格式有點類似這樣: 

for { set i 0} {$i < 10} { incr i} {puts $i} 

将會輸出從1到9的整數。 

如果用while循環,這個句子可以寫成 

while {$i < 10 } { 

puts $i; 

incr i; 

foreach是對于集合中的每一個元素執行一次指令,大緻的指令格式是 

foreach [變量] { 集合 } { 

語句; 

例如 

% foreach j { 1 3 5} { 

put $j; 

函數 

如同在一般的程式設計語言裡面一樣,在tcl裡面也可以定義函數,這是通過proc指令實作 

的: 

proc my_proc {i}{ 

puts $i; 

這樣就定義了一個名字叫proc的函數,它隻是在終端顯示輸入變元的内容。 

要使用這個函數,簡單地輸入它的名字: 

% my_proc { 5 } 

如果變元的數目是0,隻要使用空的變元清單,例如 proc my_proc {} {語句;} 

盡管tcl還可以處理更複雜的過程,但是我們不再介紹了,例如檔案的讀寫以及tk圖形 

語言,因為我們處理tcl的主要目标就是了解expect,對于更複雜的程式設計工作,我們建議 

你使用perl。 

11.1.2 expect 

expect是建立在tcl基礎上的一個工具,它用來讓一些需要互動的任務自動化地完成。 

我們首先從一個簡單的例子開始,如同在這一節一開始就提到的,我們想設定一個自動 

的檔案下載下傳程式。 

我們看一看這樣的一個例子腳本: 

#! /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" 

這個是什麼意思?呵呵,就是個自動下載下傳程式。第一行說明這個程式應該調用/usr/b 

in/expect去執行,然後的就是expect指令。 

察看expect的手冊頁面(man expect)可以得到一個很長的expect說明,可惜其中關于 

expect的文法仍然介紹的不夠。一般來說,expect主要用在需要自動執行人機互動的過 

程中,例如fsck程式,這個程式會不斷地提問"yes/no",像這樣的指令就可以用expect 

來完成。 

spawn語句在expect腳本中用于啟動一個新的程序,在我們的程式中,spawn ftp 202 

.199.248.11就是去執行ftp程式,接下來,就是expect和send的指令對了。 

每一對expect和send指令代表一個資訊/回應。如果這樣說不好了解的話,那麼可以看 

一看ftp的具體執行過程: 

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): 

顯然,一旦連接配接成功,伺服器會傳回一個Name(202.199.248.11:wanghy):的字元串來 

要求客戶給出使用者名。expect語句簡單地在傳回資訊中查詢你給出的字元串,一旦成功 

就執行下面的指令,現在,expect " Name"已經成功地找到了Name字元串,接下來可以 

執行send指令了。 

send指令比expect指令更簡單,它簡單地向标準輸入送出你設定的字元串,現在設定 

為send "ftpr"表示等到登入資訊之後就給出一個輸入ftp回車,也就是标準的登入過 

程。 

下面的行與這些行完全一樣,隻是機械地等待伺服器的回應,并且送出自己的輸入。 

要使用這個expect腳本,你隻需要将它設定為可執行的屬性,然後執行它,expect就 

會執行你需要的服務。 

由于expect是tcl的擴充,是以你在expect檔案中可以象tcl腳本一樣設定變量和程式 

流程。 

現在我們看一看我們還能夠如何改進我們的expect腳本。ftp指令可能會失敗,比如遠 

端的機器可能會無法提供服務,或者在啟動ftp指令時本地機器發生問題。為了處理這一 

類的問題,我們可以使用expect的timeout選項來設定逾時的話expect腳本自動退出: 

#! /usr/bin/expect 

spawn ftp 202.199.248.11 

expect { 

timeout exit 

Connect 

……………… 

注意這裡面使用的花括号。它的含義是使用一組并清單達式。使用并清單達式的主要 

原因是這樣:如果使用下面的指令對: 

expect timeout 

exit 

那麼由于expect腳本是順序執行的,那麼當程式執行到這個expect的時候就會阻塞, 

是以程式會一直等待到timeout然後退出。并清單達式則是相當于switch的行為,隻要列 

出的幾項内容有一項得到滿足,expect指令就得到滿足,于是程式可以正常執行。上面 

的腳本表示,如果連接配接ftp的時候發生了逾時,那麼就退出,否則,一旦發現Connect應 

答,說明伺服器已經正常了,那麼就可以繼續運作了。 

我們可以看看用tcl能夠對我們的expect腳本提供什麼幫助。我們可以設定讓expect腳 

本不斷地連接配接遠端伺服器的服務,直到正常建立連接配接開始,為此,我們可以把建立連接配接 

的指令放在一個循環裡面,并且根據回應的不同自動選擇重新輸入指令還是繼續執行: 

spawn ftp 

while {1} { 

expect "ftp>" 

send "o 202.199.248.11r" 

expect { 

"Connected" break 

"refused" { sleep 10} ; 

這裡使用了我們在tcl語言中講到的while和break指令,熟悉C的讀者應該很容易看出 

它的行為:不斷地等待ftp>提示符,在提示符下面發送連接配接遠端伺服器的指令,如果服 

務器回應是refused(連接配接失敗),就等待10秒鐘,然後開始下一次循環;如果是Conne 

cted,那麼就跳出循環執行下面的指令。sleep是expect的一個标準指令,表示暫停若幹 

秒鐘。 

expect還支援許多更複雜的程序控制方式,如fork,disconnect等等,你可以從手冊 

頁面中得到詳細的資訊。另外,各種tcl運算符和流程控制指令,包括tcl函數也可以使 

用。 

有些讀者可能會問,如果expect執行的話是否控制台輸入不能使用了,答案是否定的 

。expect指令運作時,如果某個等待的資訊沒有得到,那麼程式會阻塞在相應的expect 

語句處,這時,你在鍵盤上輸入的東西仍然可以正常地傳遞到程式中去,其實對于那些 

expect處理的資訊,原則上你輸入的内容仍然有效,隻是expect的反映太快,總是搶在 

你的前面“輸入”就是了。知道了這一點之後,你就可能寫一個expect腳本,讓expect 

自動處理來自fscki的那些惡心的yes/no選項(我們介紹過,這些yes/no其實完全是多餘 

的,正常情況下你除了選擇yes之外什麼也幹不了)。 

預設下,expect在标準輸出(你的終端上)輸出所有來自應用程式的回應資訊,你可 

以用下面的兩個指令重定向這些資訊: 

log_file [檔案名] 

這個指令讓expect在你設定的檔案中記錄輸出資訊。必須注意,這個選項并不影響控 

制台輸出資訊,不過如果你通過crond設定expect腳本在半夜運作的話,你就确實可能需 

要這個指令來記錄各種資訊了。例如: 

log_file expect.log 

log_user 0/1 

這個選項設定是否顯示輸出資訊,設定為1時是預設值,為0 的話,expect将不産生任 

何輸出資訊,或者說簡單地過濾掉控制台輸出。必須記住,如果你用log_user 0關閉了 

控制台輸出,那麼你同時也就關閉了對記錄檔案的輸出。 

這一點很讓人困擾,如果你确實想要記錄expect的輸出卻不想讓它在控制台上制造垃 

圾的話,你可以簡單地把expect的輸出重定向到/dev/null: 

./test.exp > /dev/null 

你可以象下面這樣使用一對fork和disconnect指令。expect的disconnect指令将使得 

相應的程序到背景執行,輸入和輸出被重定向到/dev/null: 

if [fork]!=0 exit 

disconnect 

fork指令會産生出一個子程序,而且它産生傳回值,如果傳回的是0,說明這是一個子 

程序,如果不為0,那麼是父程序。是以,執行了fork指令之後,父程序死亡而子程序被 

disconnect指令放到背景執行。注意disconnect指令隻能對子程序使用。

 發表于: 2007-08-15,修改于: 2007-08-15 22:13