expect實現自動交互由淺入深

expect實現自動交互由淺入深

作爲運維人員可以通過Shell可以實現簡單的控制流功能,如:循環、判斷等。但是對於需要交互的場合則必須通過人工來干預,有時候我們可能會需要實現和交互程序如telnet服務器等進行交互的功能。而Expect就使用來實現這種功能的工具。Expect是一個免費的編程工具語言,用來實現自動和交互式任務進行通信,而無需人的干預。

安裝expect,直接yum install expect -y

expect中相關命令

命令解釋
spawn啓動新的進程
send用於向進程發送字符串
expect從進程接收字符串
interact允許用戶交互
exp_continue匹配多個字符串在執行動作後加此命令

一般步驟:

啓動expect進程(spawn)--> 接收進程字符串(expect) --> 匹配字符串,成功發送字符串(send),否則等待 --> 結束

好了就直接步入主題吧,不扯那些沒用的。直接上實例:

一. 入門例子:實現自動登錄

[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權限即可。

二. 使用變量:

[root@localhost shell.sh]# vim test.exp

#!/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開始

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 [email protected]'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{...}:打印結束的提示信息。

五. shell腳本調用expect(1)

[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 [email protected]'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(2)

通過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所有報錯。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章