做爲運維人員能夠經過Shell能夠實現簡單的控制流功能,如:循環、判斷等。可是對於須要交互的場合則必須經過人工來干預,有時候咱們可能會須要實現和交互程序如telnet服務器等進行交互的功能。而Expect就使用來實現這種功能的工具。Expect是一個免費的編程工具語言,用來實現自動和交互式任務進行通訊,而無需人的干預。web
安裝expect,直接yum install expect -y
shell
命令 | 解釋 |
---|---|
spawn | 啓動新的進程 |
send | 用於向進程發送字符串 |
expect | 從進程接收字符串 |
interact | 容許用戶交互 |
exp_continue | 匹配多個字符串在執行動做後加此命令 |
通常步驟:編程
啓動expect進程(spawn)--> 接收進程字符串(expect) --> 匹配字符串,成功發送字符串(send),不然等待 --> 結束vim
好了就直接步入主題吧,不扯那些沒用的。直接上實例:bash
[root@localhost shell.sh]# vim test.exp #!/usr/bin/expectset timeout 30 spawn ssh -l root 192.168.1.106 expect { "(yes/no)?" { send "yes\r" } "password:" { send "jiajie\r" } } interact
參數 | 解釋 |
---|---|
#!/usr/bin/expect | 說明使用的shell環境 |
set timeout 30 | 設置超時時間,單位爲秒,-1爲沒有限制 |
spawn ssh... | 須要執行的命令,這裏是ssh登錄命令 |
expect "(yes/no)?" | 判斷上次輸出結果裏是否包含(yes/no)?的字符串 |
send "yes\r" | 執行交互動做,接軌上一個命令,若是上面的expect執行成功,則發送yes |
interact | 執行完成後保持交互狀態,把控制權交給控制檯 |
執行該實例:./test.exp
服務器
若是報錯-bash: ./test.exp: Permission denied
,給744權限便可。markdown
[root@localhost shell.sh]# vim test.expapp
#!/usr/bin/expect set ip 192.168.1.106 set user root set password jiajie set timeout 30 spawn ssh -l $user $ip expect { "(yes/no)?" { send "yes\r";exp_continue } "password:" { send "$password\r" } } interact
set:設置變量,後面直接變量,經過「$變量名」來調用運維
[root@localhost shell.sh]# vim test.exp #!/usr/bin/expect if {$argc!=3} { send_user "Usage:expect need three arguments:ip user password\n" exit 1 } set ip [lindex $argv 0] set user [lindex $argv 1] set password [lindex $argv 2] set timeout 30 spawn ssh -l $user $ip expect { "(yes/no)?" { send "yes\r";exp_continue } "password:" { send "$password\r" } } interact
[lindex $argv num]:表示位置參數,從num=0開始ssh
send_user: 打印當前提示,至關於shell裏的echo.
[root@localhost shell.sh]# vim test.exp #!/usr/bin/expect if {$argc!=3} { send_user "Usage:expect need three arguments:ip user password\n" exit 1 } set ip [lindex $argv 0] set user [lindex $argv 1] set password [lindex $argv 2] set timeout 30spawn ssh -l $user $ip expect { "(yes/no)?" { send "yes\r";exp_continue } "password:" { send "$password\r" } } expect "]#" { send "useradd jj\r" } expect "]#" { send "echo jiajie|passwd --stdin jj\r" } send "exit\r"expect eofexit -onexit { send_user "useradd jj is successfully.\n" send_user "Jobs has finished,Goodbye.\n" }
執行後的結果輸出:
[root@localhost shell.sh]# ./test.exp 192.168.1.106 root jiajie spawn ssh -l root 192.168.1.106root@192.168.1.106's password: Last login: Sat Sep 9 03:47:48 2017 from web [root@localhost ~]# useradd jj [root@localhost ~]# echo jiajie|passwd --stdin jj Changing password for user jj. passwd: all authentication tokens updated successfully. [root@localhost ~]# exitlogout Connection to 192.168.1.106 closed. useradd jj is successfully. Jobs has finished,Goodbye.
send "exit\r":登陸出當前環境。
expect eof:結束expect匹配。
exit -onexit{...}:打印結束的提示信息。
[root@localhost shell.sh]# vim test.sh #!/bin/bash ip=$1 user=$2 password=$3 expect <<EOF set timeout 10 spawn ssh -l $user $ip expect { "yes/no" { send "yes\n";exp_continue } "password" { send "$password\n" } } expect "]#" { send "useradd jj\n" } expect "]#" { send "echo jiajie|passwd --stdin jj\n" } expect "]#" { send "exit\n" } expect eof EOF
執行後的輸出結果:
[root@localhost shell.sh]# ./test.sh 192.168.1.106 root jiajie spawn ssh -l root 192.168.1.106root@192.168.1.106's password: Last login: Sat Sep 9 04:10:46 2017 from web [root@localhost ~]# useradd jj [root@localhost ~]# echo jiajie|passwd --stdin jj Changing password for user jj. passwd: all authentication tokens updated successfully. [root@localhost ~]# exit logout Connection to 192.168.1.106 closed. [root@localhost shell.sh]#
經過shell腳本經過調用expect腳本實現批量認證:
expect腳本:
[root@localhost shell.sh]# vim scp.exp #!/usr/bin/expect if {$argc!=3} { send_user "Usage:expect need three arguments lisk thks:file host dir\n" exit 1 } set srcname [lindex $argv 0] set hostname [lindex $argv 1] set destname [lindex $argv 2] set password "jiajie" spawn scp $srcname root@$hostname:$destnameset timeout 30 expect { # -timeout 2 "yes/no" {send "yes\r";exp_continue} "*password:" {send "$password\r"} # timeout {puts "expect connect failure,please contact admin.";return}} expect eofexit -onexit { send_user "Jobs has finished,Goodbye.\n" }
shell腳本:
[root@localhost shell.sh]# vim scp.sh #!/bin/bash if [[ "$#" != "2" ]];then echo "Usage:$0 src_filename des_filename" exit 0 fi IP_LIST=( 192.168.1.106 192.168.1.170 192.168.1.10) . /etc/init.d/functions for ip in ${IP_LIST[*]} do expect scp.exp $1 $ip $2 &> /dev/null if [ $? -eq 0 ];then action "$ip" /bin/true else action "$ip" /bin/false fi done
scp.sh腳本經過調用expect腳原本實現分發功能。執行結果以下:
[root@localhost shell.sh]# sh scp.sh /etc/fstab /tmp/ 192.168.1.106 [ OK ] 192.168.1.170 [ OK ] 192.168.1.10 [FAILED]
由於並無192.168.1.10全部報錯。