“shell是世界上最好的腳本語言!”🌚🌚🌚
shell腳本雖然可以很友善的幫我處理一些瑣碎的問題,但同時也有它的缺點:shell腳本是一種無互動式的腳本
什麼叫無互動式呢,比如說删除這個指令
[[email protected] ~]# rm test
rm:是否删除普通檔案 "test"?
在删除一個檔案時,系統會給一條互動資訊詢問是否要删除檔案,是以删除一個檔案需要有兩個操作:删除->确認删除(當然你也可以加-f來強制删除就不會有這個互動過程了,這裡隻是舉一個例子),而shell執行指令時實際上隻能一條一條的執行,并不能處理這些互動過程
是以這就引出了本文的主角:expect,一種互動式的腳本工具
其他我就不多說了,直接來将expect怎麼使用吧
- 安裝:
yum install expect
- 編寫expect腳本:
- 腳本名一般以
結尾.exp
- 第一行為
#!/usr/bin/expect
- 腳本名一般以
- 定義變量:
-
set 變量名 值
-
:從指令參數數組中取值set 變量名 [lindex $argv 0]
- 特殊變量:
-
:參數個數,相當于shell中的$argc
$#
-
:所有參數的數組,索引從0開始$argv
-
-
- 語句:
-
set 定義變量
-
:将逾時時間設定成300(秒)set timeout 300
-
-
:監控指令的輸出spawn COMMAND
-
:捕獲輸出,并執行相應指令expect “STRING” { send “STRING” }
-
:發送“STRING”,比如删除檔案時需要回複yes表示确認删除,就可以寫send “STRING\r”
,注意最後需要換行,不然輸出結果看起來會比較亂send “yes\r”
-
:執行expect時前台會被占用,這裡相當于在執行完腳本中的某一個任務時發給終端的一條提示,相當于shell中的send_user “STRING”
echo
-
:繼續捕獲輸出,expect用{}框起來的塊中可以實作類似case的判斷效果,這裡的exp_continue就相當于case語句中每一判斷條件的breakexp_continue
-
:暫停腳本的執行,将控制權交還給使用者,直到使用者interact
-
:退出腳本exit
-
:捕獲退出信号,若捕獲不到則會阻塞等待,逾時自動退出expect eof
-
下面是一些相關例子:
模拟ftp登入并下載下傳檔案
- 工作準備:
- 關閉防火牆:
iptable -F
-
yum install vsftpd
-
systemctl restart vsftpd
-
cp /etc/fstab /var/ftp
-
yum install ftp
- 關閉防火牆:
#!/usr/bin/expect
set ip [lindex $argv 0]
set name "ftp"
set pass ""
set file "fstab"
spawn ftp $ip
expect "Name"
send "$name\r"
expect "Password"
send "$pass\r"
expect ">" {
send "get $file ftp_$file\r"
send "exit\r"
}
expect eof
send_user "ALL COMMAND FINISHDED\n"
測試用例:
[[email protected] ~]# ./ftp.exp 127.0.0.1
spawn ftp 127.0.0.1
Connected to 127.0.0.1 (127.0.0.1).
220 (vsFTPd 3.0.2)
Name (127.0.0.1:root): ftp
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> get fstab ftp_fstab
local: ftp_fstab remote: fstab
227 Entering Passive Mode (127,0,0,1,246,62).
150 Opening BINARY mode data connection for fstab (501 bytes).
226 Transfer complete.
501 bytes received in 0.000192 secs (2609.38 Kbytes/sec)
ftp> exit
221 Goodbye.
ALL COMMAND FINISHDED
[[email protected] ~]#
[[email protected] ~]# ll | grep 'ftp_'
-rw-r--r--. 1 root root 501 3月 5 22:28 ftp_fstab
用shell腳本批量分發公鑰(将所有)
- 建立密鑰分發expect腳本
key.exp
#!/usr/bin/expect
set timeout 300
set password "redhat"
set ip [lindex $argv 0]
spawn ssh-copy-id [email protected]$ip
expect {
"yes/no" {
send "yes\r"
exp_continue
}
"password: " {
send "$password\r"
exp_continue
}
"No route to host" {
exit 1
}
eof
}
- 建立shell腳本,調用expect
#!/bin/bash
. /etc/init.d/functions
for i in `cat /root/ip.txt`; do
expect /root/key.exp $i > /dev/null 2>&1
if [ $? -eq 0 ]; then
action "$i" /bin/true
else
action "$i" /bin/false
fi
done