expect: spawn id exp6 not open while executing "expect eof"


1.expect是基於tcl演變而來的,所以很多語法和tcl類似

基本的語法如下所示:
1.1 首行加上/usr/bin/expect
1.2 spawn: 后面加上需要執行的shell命令,比如說spawn sudo touch testfile
1.3 expect: 只有spawn執行的命令結果才會被expect捕捉到,因為spawn會啟動一個進程,只有這個進程的相關信息才會被捕捉到,主要包括:標准輸入的提示信息,eof和timeout。
1.4 send和send_user:send會將expect腳本中需要的信息發送給spawn啟動的那個進程,而send_user只是回顯用戶發出的信息,類似於shell中的echo而已。

一個小例子,用於linux下賬戶的建立:

filename: account.sh,可以使用./account.sh newaccout來執行;

#!/usr/bin/expect

set passwd "mypasswd"
set timeout 60

if {$argc != 1} {
    send "usage ./account.sh \$newaccount\n"
    exit
}

set user [lindex $argv [expr $argc-1]]

spawn sudo useradd -s /bin/bash -g mygroup -m $user

expect {
    "assword" {
        send_user "sudo now\n"
        send "$passwd\n"
        exp_continue
    }
    eof
    {
        send_user "eof\n"
    }
}

spawn sudo passwd $user
expect {
    "assword" {
        send "$passwd\n"
        exp_continue
    }
    eof
    {
        send_user "eof"
    }
}

spawn sudo smbpasswd -a $user
expect {
    "assword" {
        send "$passwd\n"
        exp_continue
    }
    eof
    {
        send_user "eof"
    }
}

注意點:

第3行: 對變量賦值的方法;
第4行: 默認情況下,timeout是10秒;
第6行: 參數的數目可以用$argc得到;
第11行:參數存在$argv當中,比如取第一個參數就是[lindex $argv 0];並且如果需要計算的話必須用expr,如計算2-1,則必須用[expr 2-1];
第13行:用spawn來執行一條shell命令,shell命令根據具體情況可自行調整;有文章說sudo要加-S,經過實際測試,無需加-S亦可;
第15行:一般情況下,如果連續做兩個expect,那么實際上是串行執行的,用例子中的結構則是並行執行的,主要是看匹配到了哪一個;在這個例子中,如果你寫成串行的話,即

expect "assword"
send "$passwd\n"
expect eof
send_user "eof"

那么第一次將會正確運行,因為第一次sudo時需要密碼;但是第二次運行時由於密碼已經輸過(默認情況下sudo密碼再次輸入時間為5分鍾),則不會提示用戶去輸入,所以第一個expect將無法匹配到assword,而且必須注意的是如果是spawn命令出現交互式提問的但是expect匹配不上的話,那么程序會按照timeout的設置進行等待;可是如果spawn直接發出了eof也就是本例的情況,那么expect "assword"將不會等待,而直接去執行expect eof。 這時就會報expect: spawn id exp6 not open,因為沒有spawn在執行,后面的expect腳本也將會因為這個原因而不再執行;所以對於類似sudo這種命令分支不定的情況,最好是使用並行的方式進行處理;
第17行:僅僅是一個用戶提示而已,可以刪除;
第18行:向spawn進程發送password;
第19行:使得spawn進程在匹配到一個后再去匹配接下來的交互提示;
第21行:eof是必須去匹配的,在spawn進程結束后會向expect發送eof;如果不去匹配,有時也能運行,比如sleep多少秒后再去spawn下一個命令,但是不要依賴這種行為,很有可能今天還可以,明天就不能用了;

其他

下面這個例子比較特殊,在整個過程中就不能expect eof了:

#!/usr/bin/expect

set timeout 30
spawn ssh 10.192.224.224
expect "password:"
send "mypassword\n"
expect "*$"
send "mkdir tmpdir\n"

expect "*$"

timeout指expect等待命令至多等30seconds
這個例子實際上是通過ssh去登錄遠程機器,並且在遠程機器上創佳一個目錄,我們看到在我們輸入密碼后並沒有去expect eof,這是因為ssh這個spawn並沒有結束,而且手動操作時ssh實際上也不會自己結束除非你exit;所以你只能expect bash的提示符,當然也可以是機器名等,這樣才可以在遠程創建一個目錄。

注意,請不要用spawn mkdir tmpdir,這樣會使得上一個spawn即ssh結束,那么你的tmpdir將在本機建立。

當然實際情況下可能會要你確認ssh key,可以通過並行的expect進行處理,不多贅述。

覺得bash很多情況下已經很強大,所以可能用expect只需要掌握這些就好了,其他的如果用到可以再去google了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM