expect實現非交互
一、exepct介紹
expect命令是一個實現交互功能的軟件套件,是基於TCL的腳本編程語言,在企業運維中,系統會以交互的形式要求運維人員輸入指定的字符串,之後才能繼續執行命令。例如:為用戶設置密碼時,一般情況下需要手工輸入兩次密碼,比如使用ssh連接遠程服務器時,第一次連和系統實現兩次交互。
簡單的說,expect用來自動實現與交互程序通信的,無需管理員手工幹預
spawn啟動指定進程>expect獲取期待的關鍵字>send向指定進程發送字符>進程執行完畢,退出
二、expect程序自動交互
expect程序中的命令是expect的核心
spawn [選項] [需要交互的命令或程序]
例如:
spawn ssh [email protected] uptime
在spawn命令的後面,直接要加上要執行的命令或程序
expect命令語法
在expect自動交互的執行過程中,當使用spawn命令執行一個命令或程序之後,會提示某些交互信息,expect命令的作用就是獲取spawn命令執行的信息,看看是否有事先指定的相匹配,一旦匹配上指定的內容就執行expect後面的動作。
expect 表達式 [動作]
例如:
spawn ssh [email protected] uptime
expect “*password” {send “666666\r”}
send 發送字符串
當然,他也可以在一個expect匹配中多次匹配不同的字符串,並給出不同的處理動作,此時,只需要將匹配的所有字符串放在一個{}大括號中就可以了,好需要借助exp_continue指令實現繼續匹配。
2.1 實現自動交互
#!/usr/bin/expect
spawn ssh [email protected] uptime
expect {
"yes/no" {exp_send "yes\r";exp_continue}
"*password" {exp_send "666666\r"}
}
expect eof
expect_send和send類似,\r 回車
expect{},類似多行expect。
exp_continue 匹配多個字符串,需要在每次匹配並執行動作後繼續匹配,加上exp_continue
exp_eof 想要輸出結果,必須加eof,表示expect結束
2.2利用expect響應shell腳本中的多個read讀入
[root@localhost ~]# vim xinxi.sh
#!/bin/bash
read -p "pls input your username:" name
read -p "pls input your password:" pass
read -p "pls input your email:" mail
echo -n "your name is $name ,"
echo -n "your passwordis $pass ,"
echo "your emali is $mail"
[root@localhost ~]# sh xinxi.sh
pls input your username:calabash
pls input your password:666666
pls input your email:[email protected]
your name is calabash ,your passwordis 666666 ,your emali is [email protected]
用expect自動化腳本,實現自動輸入多個字符串
[root@localhost ~]# vim expxinxi.exp
#!/usr/bin/expect
spawn /bin/sh xinxi.sh
expect {
"username" {exp_send "calabash\r";exp_continue}
"password" {send "666666\r";exp_continue}
"email" {exp_send "[email protected]\r"}
}
expect eof
執行,全部自動輸入,實現了自動化
[root@localhost ~]# expect expxinxi.exp
spawn /bin/sh xinxi.sh
pls input your username:calabash
pls input your password:666666
pls input your email:[email protected]
your name is calabash ,your passwordis 666666 ,your emali is [email protected]
send_user 可以用來打印expect腳本的信息,類似shell裏的echo命令
[root@localhost ~]# vim me.exp
#!/usr/bin/expect
send_user "I am calabash. \n"
send_user "I am a linuxer. \t"
send_user "mysql email is [email protected]\n"
[root@localhost ~]# expect me.exp
I am calabash.
I am a linuxer. mysql email is [email protected]
\n 換行
\t tab鍵
exit命令類似於shell腳本的exit,即直接退出expect腳本,除了最基本的退出,還可以利用exit做一些提示
例如:
[root@localhost ~]# vim me.exp
#!/usr/bin/expect
send_user "I am calabash. \n"
send_user "I am a linuxer. \t"
send_user "mysql email is [email protected]\n"
exit -onexit {
send_user "Good bye.\n"
}
[root@localhost ~]# expect me.exp
I am calabash.
I am a linuxer. mysql email is [email protected]
Good bye.
2.3 常用命令總結
spawn:用過spawn執行一個程序或命令,之後所有的expect操作都在這個執行的程序或命令中執行。
expect:獲取spawn程序的交互信息,查看是否和其事先指定的信息想匹配。
send:當expect匹配了指定的字符串後,發送指定的字符串給系統,這些命令可以支持一些特殊的轉義符號,例如: \r回車 \n換行 \t tab等
exp_contine:繼續匹配expect程序或命令
send_user:打印腳本信息
exit:退出expect腳本,也可以做清理或提示工作
三、expect程序變量
3.1普通變量
定義變量:
set 變量名 變量值
打印變量:
puts $變量名
示例:
[root@localhost ~]# vim shili.exp
#!/usr/bin/expect
set password "666666"
puts $password
send_user "$password\n"
[root@localhost ~]# expect shili.exp
666666
666666
3.2 特殊參數變量
在expect裏也有與shell腳本裏的$0 $1 $2 等類似的特殊參數變量,用於接收控制expect腳本傳參
在expect中$argv表示參數數組,可以使用[lindex $argv n]接收expet腳本傳參,n從0開始,分別表示第一個[lindex $argv 0]參數、第二個[lindex $argv 1]、第三個[lindex $argv 2參數]
例如:
[root@localhost ~]# vim shili.exp
#!/usr/bin/expect
set file [lindex $argv 0]
set host [lindex $argv 1]
set dir [lindex $argv 2]
puts "$file\t $host\t $dir\n"
puts $argc
puts $argv0
加三個位置參數
[root@localhost ~]# expect shili.exp a.txt 192.168.4.5 /root
a.txt 192.168.4.5 /root
3
shili.exp
$argc 表示傳參的個數
$argv0 表示腳本本身的名字
3.3 關鍵字變量
timeout是一個控制時間的關鍵字變量,是一個全局性時間的控制開關,可以通過為這個變量賦值來規定整個expect操作的時間。因為作用於全局,即使命令沒有錯誤,到了時間仍然會激活這個變量,此外,到時間後還會激活一個處理及提示信息開關。
示例:
此腳本測試超時返回值,所以不設置密碼,5秒後超時返回
[root@localhost ~]# vim shili.exp
#!/usr/bin/expect
spawn ssh [email protected] uptime
set timeout 5
expect "yes/no" {exp_send "yes\r;exp_continue"}
expect timeout {puts "Request timeout by calabash.";return}
[root@localhost ~]# expect shili.exp
spawn ssh [email protected] uptime
[email protected]‘s password: Request timeout by calabash.
此外,在expect{}用法,還可以這樣使用timeout
[root@localhost ~]# vim shili.exp
#!/usr/bin/expect
spawn ssh [email protected] uptime
expect {
-timeout 3
"yes/no" {exp_send "yes\r";exp_continue}
timeout {puts "Request timeout by calabash.";return}
}
[root@localhost ~]# expect shili.exp
spawn ssh [email protected] uptime
[email protected]‘s password: Request timeout by calabash.
四、expect程序中的if條件語句
4.1 if語句的語法
if { 條件表達式 } {
指令
}
或者
if { 條件表達式 } {
指令
} else {
指令
}
註意:if關鍵字後面要有空格,else關鍵字前後要有空格
{條件表達式} 大括號裏可以沒有空格, 外面前後要有空格
4.2 if判斷示例
使用if語句判斷腳本傳參的個數,不管是否符合都給予提示
[root@localhost ~]# vim shili.exp
#!/usr/bin/expect
if { $argc != 26 } {
puts "bad."
} else {
puts "good."
}
[root@localhost ~]# expect shili.exp
bad.
[root@localhost ~]# expect shili.exp {a..z}
good.
五、expect生產環境案例
5.1 實現自動交互的腳本
[root@G ~]# vim zd.exp
#!/usr/bin/expect
if { $argc != 2 } {
puts "usage: expect $argv0 ip command"
exit
}
#
set ip [lindex $argv 0]
set cmd [lindex $argv 1]
set password "666666"
#
spawn ssh root@$ip $cmd
expect {
"yes/no" {send "yes\r";exp_continue} &> /dev/null
"*password" {send "$password\r"} &> /dev/null
}
expect eof
腳本後加上ip和命令
[root@G ~]# expect zd.exp 192.168.4.5 uptime
spawn ssh [email protected] uptime
[email protected]‘s password:
05:15:09 up 15 min, 2 users, load average: 0.00, 0.00, 0.00
5.2 利用for循環查看多臺
現有2臺服務器,需要用管理機去查看
Ip地址 |
主機名 |
角色 |
192.168.4.4 |
G |
管理機 |
192.168.4.5 |
b1 |
被管理機 |
192.168.4.6 |
b2 |
被管理機 |
[root@G ~]# vim pl.sh
#!/bin/bash
if [ $# -ne 1 ];then
echo $"USAGE:$0 cmd"
exit 1
fi
cmd=$1
for n in 5 6
do
expect zd.exp 192.168.4.$n "$cmd"
done
[root@G ~]# sh pl.sh uptime
spawn ssh [email protected] uptime
[email protected]‘s password:
01:00:21 up 36 min, 2 users, load average: 0.00, 0.00, 0.00
spawn ssh [email protected] uptime
[email protected]‘s password:
01:00:21 up 35 min, 2 users, load average: 0.00, 0.00, 0.00
5.3 免交互發送文件
[root@G ~]# vim scpfile.exp
#!/usr/bin/expect
if { $argc != 3 } {
puts "usage: expect $argv0 file host dir"
exit
}
#
set file [lindex $argv 0]
set host [lindex $argv 1]
set dir [lindex $argv 2]
set password "666666"
spawn scp -rp -P22 $file root@$host:$dir
expect {
"yes/no" {send "yes/r";exp_continue}
"*password" {send "$password\r"}
}
expect eof
發送文件
[root@G ~]# expect scpfile.exp abc 192.168.4.6 /root/
spawn scp -rp -P22 abc [email protected]:/root/
[email protected]‘s password:
查看發送結果
[root@G ~]# expect zd.exp 192.168.4.6 ls
spawn ssh [email protected] ls
[email protected]‘s password:
abc
anaconda-ks.cfg
install.log
install.log.syslog
5.4 利用shell循環批量發送文件
[root@G ~]# vim scpfile.sh
#!/bin/bash
if [ $# -ne 2 ];then
echo $"USAGE:$0 file dir"
exit 1
fi
#
file=$1
dir=$2
for n in 5 6
do
expect scpfile.exp $file 192.168.4.$n $dir
done
[root@G ~]# sh scpfile.sh wangluyu /root/
spawn scp -rp -P22 wangluyu [email protected]:/root/
[email protected]‘s password:
spawn scp -rp -P22 wangluyu [email protected]:/root/
[email protected]‘s password:
expect實現非交互