自动化运维的过程中,某些时候我们需要受用输入密码,这时候Expect这个工具可以完成。


首先要安装expect,直接yum安装就可以的。

下来我们试试expect这个工具:

使用ssh登陆:

#!/bin/expect                                      #脚本解释器
spawn ssh root@192.168.116.137  uptime             #开启expect自动交互,执行ssh命令
expect "*password" {send "123456\n"}               #如果ssh命令输出匹配*password,就发送123456给系统
expect eof                                         #表示交互结束

下来时匹配多个expect:

#!/bin/expect

spawn ssh root@192.168.116.136  uptime

expect {                                       #将多个字符放在expect里面,然后spawn执行的过程中进行匹配
  "yes/no" {exp_send "yes\r";exp_continue}      #exp_send和前面的send一样,匹配多个字符串在每次匹配并执行动作后,加上exp_continue
  "*password" {exp_send "123456\n"}
}
expect eof

利用expect响应shell脚本中的多个read读入:

shell脚本:
#!/bin/bash
read -p "plz input your username:" name
read -p "plz input your password:" pass
echo -en "your username $name,your password $pass\n"
~
expect脚本:
#!/bin/expect
spawn sh /root/32.sh
expect {
  "username" {exp_send "xpg\r";exp_continue}
  "password" {exp_send "123456\n"}
}
expect eof
~

18.4.5 send_user命令

相当于echo -n这个命令:

#!/bin/expect
send_user "I AM OLDBOY\n"
send_user "I am who?\n"

18.4.6 exit命令

类似shell中的shell,直接退出expect脚本,除了基本的退出脚本功能之外,还可以利用这个脚本做一些关闭前的清理和提示等工作:

#!/bin/expect
send_user "I AM OLDBOY\n"
send_user "I am who?\n"
exit -onexit {
  send_user "Good bye\n"
}

18.5 Expect程序变量

18.5.1普通变量

定义变量的基本语法如下:

set   变量名   变量值

打印:

puts   $变量名

#!/bin/expect
set password "123456"
puts $password

18.5.2特殊参数变量

在expect里有与shell脚本里的$0,$1,$2等类似的特殊参数变量,用于接收及控制expect脚本传参。

在expect中$argv表示参数数组,可以使用[lindex  $argv n]接收expect脚本传参,n从0开始,分别表示第一个[lindex $argv0] 参数、

例如:

#!/bin/expect
set file [lindex $argv 0]
set user [lindex $argv 1]
set dir  [lindex $argv 2]

puts $argv0
puts $argc
puts $file
send_user "your name is $user;your dir is $dir\n"

18.6 Expect程序中的if条件语句

if { 表达式 } {

    指令

}

或者

if { 条件表达式 }  {

    指令

}else  {

指令

}

范例18-9 使用if语句判断脚本传参的个数,如果不符合给予提示:

#!/bin/expect
if { $argc != 3 } {
   send_user "usage:expect $argv0 file host dir/n"
   exit -onexit {
   send_user "Good bye bye"
   }
}
set file [lindex $argv 0]
set host [lindex $argv 1]
set dir  [lindex $argv 2]

puts $file
puts $argv0
puts $argc
~

18.7 timeout 关键字

这个关键字是服务于全局的,而不是某一个;和shell中的sleep很像,休息30s。

18.8企业生产场景下expect案例

  1. 开发expect自动交互的脚本:

#!/bin/expect
if { $argc != 2 } {
   send_user "usage:expect $argv0 ip cmd/n"
   exit
   }

set ip   [lindex $argv 0]
set cmd  [lindex $argv 1]
#set dir  [lindex $argv 2]
spawn ssh root@$ip  $cmd
expect {
   "yes/no" {exp_send "yes\r";exp_continue}
   "*password" {exp_send "123456\n"}
}
expect eof

上面是一个,我们向想办法批量执行execpt脚本试试:

用这个脚本调用上面的脚本,就可以实现循环批量

#!/bin/bash
if [ $# - ne 1 ]
  then
    echo "USAGE:$0 cmd"
    exit
fi

cmd=$1

for i in 136 137
do
  expect /root/4.exp 192.168.116.$i $cmd
done

18.8自动化 批量发送文件 **

下面这两个脚本相结合就能实现

#cat 5.exp
#!/bin/expect

if { $argc != 3 } {
  send_user "plz input:usage $argv0 ip cmd"
  exit
}
set file [lindex $argv 0]
set ip   [lindex $argv 1]
set dir  [lindex $argv 2]

spawn scp -rp $file root@$ip:$dir

expect {
  "yes/no" {exp_send "yes\r";exp_continue}
  "*password" {exp_send "123456\n"}
}
expect eof
#cat 55.sh
#!/bin/bash
if [ $# -ne 2 ]; then
   echo "plz input $0 file dir"
   exit
fi
file=$1
dir=$2
for i in 136 137
do
   expect 5.exp $file 192.168.116.$i $dir
done
~