很多時候我們需要在指令碼裡面通過FTP或是其他方式取另外一台機器上的檔案,為安全起見而登入另外一台機器一般都需要使用者認證。這裡的例子在sh指令碼中調用expect指令碼實現自動互動。
Expect是一個用來實現自動交談功能的軟體,Expect是在TCL語言基礎上建立的,它還提供了一些TCL語言所沒有的命令。例如spawn命令啟動一個Unix/Linux程式來進行互動的運行,Send命令向程式發送字串,expect命令等待送進的某些字串。
expect.sh檔案內容:
----------------------------------------------------------------------------------------------------------------
#!/usr/bin/expect -f
if {[lindex $argv 0] == "getinfo"} {
set FIRST_TIME "N"
spawn sftp username@192.168.0.1
expect {
"* (yes/no)? " {
set FIRST_TIME "Y"
sleep 1
send "yes/r"
}
"* password: " {
sleep 1
send "password/r"
}
timeout {
exit 2
}
}
if { "$FIRST_TIME" == "Y" } {
expect {
"* password: " {
sleep 1
send "password/r"
}
timeout {
exit 2
}
}
}
expect "sftp> "
send "ls -all [lindex $argv 1]/r"
expect "sftp> "
exit 0
}
if {[lindex $argv 0] == "download"} {
spawn sftp username@192.168.0.1
expect {
"* password: " {
sleep 1
send "password/r"
}
timeout {
exit 2
}
}
set timeout -1
expect "sftp> "
send "get [lindex $argv 1]/[lindex $argv 2] [lindex $argv 3]/r"
expect "sftp> "
exit 0
}
----------------------------------------------------------------------------------------------------------------
這裡因為如果一台機器第一次訪問另外一台機器時,會顯示如下的確認資訊:
----------------------------------------------------------------------------------------------------------------
$ sftp username@192.168.0.1
Connecting to 192.168.0.1...
The authenticity of host '192.168.0.1 (192.168.0.1)' can't be established.
RSA key fingerprint is 8a:3e:5b:a2:dd:b1:19:2d:c9:1f:b9:69:96:15:5c:41.
Are you sure you want to continue connecting (yes/no)?
----------------------------------------------------------------------------------------------------------------
但是以後的訪問就不會出現這些認證資訊,所以使用FIRST_TIME加以區分。
這裡實現了兩個函數getinfo和download,因為指令碼下不能象C++那樣調用函數,這裡使用通過傳參數來選擇函數。第一個函數getinfo羅列目標機器上某一目錄下的檔案,第二個函數download下載目標機器上的檔案。
接下來就是sh指令碼中如何調用expect了。選擇這樣在sh中調用expect主要是因為sh功能很強大,可以在sh中實現很多功能,諸如調用sed來處理字串等。
autodownload.sh檔案的內容:
----------------------------------------------------------------------------------------------------------------
#!/bin/bash
EXPECT_SHELL="expect.sh"
TEMP_FILE="serverinfo.tmp"
#get server target directory information and then save it into a temp local file
`exec /usr/bin/expect $WORKING_DIR/$EXPECT_SHELL getinfo $SERVER_SPIDER_DIR > ./$TEMP_FILE`
while read LINE_STR
do
# your process to get your target file & save the target file name in TARGET_FILE
done < ./$TEMP_FILE
#delete temp file
rm $TEMP_FILE
# download the target file
$DOWNLOAD_PLACE=./
`exec /usr/bin/expect ./$EXPECT_SHELL download $TARGET_FILE $DOWNLOAD_PLACE > /dev/null`
...
exit 0
----------------------------------------------------------------------------------------------------------------
2007/11/14