expect自动化交互式程序应用实践

 1、什么是 expect

expect 是一个用来实现自动交互功能的软件套件,是基于 TCL 的脚本编程工具语言,方便学习,功能强大。

2、为什么要用 expect

2.1 案例

[root@CentOS8 ~]# ssh -p22 root@10.110.81.223 uptime
The authenticity of host '10.110.81.223 (10.110.81.223)' can't be established.
ECDSA key fingerprint is SHA256:a90cAgsNSIkK3nh1uJ08NtYyo+8UMqZ/5TtdXplIgkY.
Are you sure you want to continue connecting (yes/no)? yes # 如果是第一次,那么这里还得有RSA KEY的yes/no选项
Warning: Permanently added '10.110.81.223' (ECDSA) to the list of known hosts. root@10.110.81.223's password:  06:51:05 up 33 days, 15:48, 2 users, load average: 0.88, 0.68, 0.70

2.2 描述

可以发现上述案例中,使用 SSH 远程连接服务器时,第一次连接要和系统实现两次交互。
简单来说,expect 是用来自动实现与交互式程序通信的,而无需管理员的手工干预,从而达到自动化运维的目的。

2.3 以下是 expect 的自动交互工作流程简单说明

spawn 启动制定进程->expect 获取期待的关键字->send 向指定进程发送指定字符-> 进程执行完毕,退出结束

3、安装 expect

[root@bogon xls-a]# rpm -qa expect
[root@bogon xls-a]# yum install -y expect
[root@bogon xls-a]# rpm -qa expect
expect-5.44.1.15-5.el6_4.x86_64

4、案例

4.1 案例 1-expect1

[root@CentOS8 test]# cat boxiaoyaun.exp 
#!/usr/bin/expect  # 脚本开头解析器,和shell类似,表示程序使用Expect解析
spawn ssh -p22 root@10.110.81.223 uptime # 执行ssh命令(注意开头必须要有spawn,否则无法实现交互)
expect "*password*"  # 利用expect获取执行上述ssh命令输出的字符串是否为脐带的字符串
send "密码\n"
expect eof
[root@CentOS8 test]# expect boxiaoyaun.exp 
spawn ssh -p22 root@10.110.81.223 uptime
root@10.110.81.223's password: 
 06:55:30 up 33 days, 15:53,  2 users,  load average: 0.30, 0.44, 0.59
注释:
1)在expect自动交互程序执行的过程中,spawn命令是一开始就需要使用的命令,通过spawn执行一个命令或程序,之后所有的expect操作都会在这个执行过的命令或程序进程中进行,包括自动交互功能,因此如果没有spawn命令,expect程序将会无法实现自动交互。
2)使用spawn命令是expect程序实现自动交互工作流程中的第一步,也是最关键的一步。

4.2 案例 2-expect2

[root@bogon exp]# cat 18_2_1.exp 

#!/usr/bin/expect
spawn ssh -p22 tomcat@10.10.8.17 uptime
expect { # 前始大括号要有空格
        "yes/no"        {exp_send "yes\r";exp_continue}
        "*password"     {exp_send "填写你的服务器密码\r"}
}
expect eof


[root@bogon exp]# rm -rf ~/.ssh/known_hosts

[root@bogon exp]# expect 18_2_1.exp 
spawn ssh -p22 tomcat@10.10.8.17 uptime
The authenticity of host '10.10.8.17 (10.10.8.17)' can't be established.
RSA key fingerprint is 02:c1:55:f6:9c:fd:5f:66:a5:e0:1b:51:ef:2d:c1:0d.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.10.8.17' (RSA) to the list of known hosts.
tomcat@10.10.8.17's password: 
 15:39:22 up 2 days,  3:56,  1 user,  load average: 0.08, 0.06, 0.05
注释:
1)expect{},类似多行expect
2)exp_send和send类似,后面的\r(回车)和前文\n(换行)类似。 3)匹配多个字符串,需要在每次匹配并执行动作后,加上exp_continue,即让expect程序继续匹配,注意exp_continue前面的分号";"。

4.3 案例 3-read-exp_send-send

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

#注意下面的单引号和双引号。
[root@bogon exp]# cat 18_3_1.sh 

#!/bin/sh
read -p 'input username :' name
read -p 'input password :' pass
read -p 'input email :' email
echo -n "your name is $name,"
echo -n "your pass is $pass,"
echo -n "your email is ${email}."

[root@bogon exp]# /bin/sh 18_3_1.sh 
input username :nameval
input password :passval      
input email :emailval
your name is nameval,your pass is passval,your email is emailval.

注释: exp_send和send都是expect中的动作命令,用法类似,即在expect命令匹配指定的字符串后,发送指定的字符串给系统。

[root@bogon exp]# cat 18_3_2.exp   

#!/usr/bin/expect
spawn /bin/sh 18_3_1.sh
expect {
        "username"      {exp_send "testname\r";exp_continue}
        "*pass*"        {send "123456\r";exp_continue}
        "*mail*"        {exp_send "123456@qq.com\r"}
}
expect eof

[root@bogon exp]# expect 18_3_2.exp
spawn /bin/sh 18_3_1.sh
input username :testname
input password :123456
input email :123456@qq.com
your name is testname,your pass is 123456,your email is 123456@qq.com.

4.4 案例 4-send_user

[root@bogon exp]# cat 18_4_1.exp 

#!/usr/bin/expect
send_user "i am boy.\n"
send_user "i am linux.\n"
send_user "blog is llyweb.\n"
[root@bogon exp]# expect 18_4_1.exp 
i am boy.
i am linux.
blog is llyweb.

注释: send_user命令可用来打印expect脚本信息,类似shell的echo命令。

4.5 案例 5-exit

[root@bogon exp]# cat 18_4_2.exp 

#!/usr/bin/expect
send_user "i am boy.\n"
send_user "i am linux.\n"
send_user "blog is llyweb.\n"
exit -onexit {
        send_user "good bye.\n"
}
[root@bogon exp]# expect 18_4_2.exp 
i am boy.
i am linux.
blog is llyweb.
good bye.

注释: exit命令类似于shell中的exit,即直接退出expect脚本,除了最基本的退出脚本功能以外, 还可以利用这个命令对脚本做一些关闭前的清理和提示等工作。

4.6 案例 6-普通变量

[root@bogon exp]# cat 18_6_1.exp       

#!/user/bin/expect
set password "123456"
puts $password  # 打印变量
send_user "${password}.\n"

[root@bogon exp]# expect 18_6_1.exp 
123456
123456.

4.7 案例 7-特殊参数变量

[root@bogon exp]# cat 18_8_1.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"
puts $argc
puts $argv0
[root@bogon exp]# expect 18_8_1.exp yijiananzhuang.sh 10.10.8.17 /home/tomcat/yijiananzhuang
yijiananzhuang.sh       10.10.8.17      /home/tomcat/yijiananzhuang
3
18_8_1.exp

注释: 在expect中$argv表示参数数组,可以使用[lindex $argv n]接收expect脚本传参。 $argc表示传参的个数 $argv0表示脚本的名字。

4.8 案例 8-if-else

[root@bogon exp]# cat 18_10_1.exp 

#!/usr/bin/expect
if {$argc != 26} {
        puts "bad."
} else {
        puts "good."
}
[root@bogon exp]# expect 18_10_1.exp 
bad.
[root@bogon exp]# expect 18_10_1.exp {a..z}
good.

说明:if关键字后面要有空格,else关键字前后都要有空格,{条件表达式}大括号里面靠近大括号处可以没有空格,将指令括起来的起始大括号"{"前要有空格。

4.9 案例 9-关键字-eof-timeout

注释:
expect 中的特殊关键字用于匹配过程,代表某些特殊的含义或状态,一般只用于 expect 命令中而不能在 expect 命令外单独使用。

[root@bogon exp]# cat 18_1_1.exp 

#!/usr/bin/expect
spawn ssh -p22 tomcat@10.10.8.17 uptime
expect "*password*"
send "填写你的服务器密码\n"
expect eof

[root@bogon exp]# expect 18_1_1.exp 
spawn ssh -p22 tomcat@10.10.8.17 uptime
tomcat@10.10.8.17's password: 
 21:41:17 up 3 days,  9:58,  1 user,  load average: 0.02, 0.04, 0.05

注释:eof关键字用于匹配结束符。

timeout是expect中的一个控制时间的关键字变量,它是一个全局性的时间控制开关,可以通过为这个变量赋值来规定整个expect操作的时间,注意这个变量是服务于expect全局的,而不是某一条命令,即使命令没有任何错误,到了时间仍然会激活这个变量,此外,到时间后还会激活一个处理及提示信息开关。

[root@bogon exp]# cat 18_11_1.exp

#!/usr/bin/expect
spawn ssh tomcat@10.10.8.17 uptime
#设置10秒超时
set timeout 10
expect "yes/no"
expect timeout
[root@bogon exp]# expect 18_11_1.exp
spawn ssh tomcat@10.10.8.17 uptime
tomcat@10.10.8.17's password:

注释:timeout设置为0表示立即超时,-1表示永不超时。

[root@bogon exp]# cat 18_11_2.exp       

#!/usr/bin/expect
spawn ssh tomcat@10.10.8.17 uptime
expect {
        -timeout 3
        "yes/no" {exp_send "yes\r";exp_continue}
        timeout  {puts "request timeout by boy.";return}
}

[root@bogon exp]# expect 18_11_2.exp 
spawn ssh tomcat@10.10.8.17 uptime
tomcat@10.10.8.17's password: request timeout by boy.

5、生产模拟案例

5.1 案例 1-uptime-"free -m"

[root@bogon exp]# cat 18_12_1.exp

#!/usr/bin/expect

if { $argc != 2 } {
        puts "usage: expect $argv0 ip command"
        exit
}
#define var
set ip [lindex $argv 0]
set cmd [lindex $argv 1]
set password "填写你的服务器密码"

spawn ssh tomcat@$ip $cmd
expect {
        "yes/no"        {send "yes\r";exp_continue}
        "*password"     {send "$password\r"}
}


[root@bogon exp]# expect  18_12_1.exp 10.10.8.17 uptime
spawn ssh tomcat@10.10.8.17 uptime
tomcat@10.10.8.17's password: 
 17:35:35 up 2 days,  5:52,  1 user,  load average: 0.01, 0.09, 0.08
[root@bogon exp]# expect  18_12_1.exp 10.10.8.17 "free -m"
spawn ssh tomcat@10.10.8.17 free -m
tomcat@10.10.8.17's password: 
              total        used        free      shared  buff/cache   available
Mem:           7731         205        7260           9         265        7257
Swap:          7935           0        7935
posted @ 2020-09-03 07:35  博小园  阅读(315)  评论(0编辑  收藏  举报
回到顶部