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進行處理,不多贅述。
