YAZONG 我的开源

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

  ,
0 评论0 浏览

1、什么是 expect

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

2、为什么要用 expect

2、1 案例

[root@bogon exp]# ssh tomcat@10.10.8.16
#如果是第一次,那么这里还得有RSA KEY的yes/no选项
tomcat@10.10.8.16's password: 
Last login: Thu Apr 30 13:41:01 2020 from 10.10.8.24
[tomcat@16 ~]$

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@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:09:57 up 3 days,  9:27,  1 user,  load average: 0.21, 0.06, 0.06

------------------

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

#!/usr/bin/expect
spawn ssh tomcat@10.10.8.17 uptime
expect "*password:" {send "填写你的服务器密码\n"}
expect eof
 
[root@bogon exp]# expect 18_1_2.exp
spawn ssh tomcat@10.10.8.17 uptime
tomcat@10.10.8.17's password: 
 21:19:21 up 3 days,  9:36,  1 user,  load average: 0.20, 0.16, 0.09

------------------

注释:
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_continue,注意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.

4、9 案例 9-关键字-eof-timeout

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


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

[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
--------------
注释: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.

[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"}
}
expect eof
[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:28:18 up 2 days,  5:45,  1 user,  load average: 0.02, 0.04, 0.05

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

5、2 案例 2-循环-uptime-"free -m"

[root@bogon exp]# cat 18_12_2.sh

#!/bin/sh
if [ $# -ne 1 ]
        then
                echo $"USAGE:$0 cmd"
                exit 1
fi
cmd=$1
for n in 17 16
do
        expect 18_12_1.exp 10.10.8.$n "$cmd"
done

[root@bogon exp]# /bin/sh 18_12_2.sh uptime
spawn ssh tomcat@10.10.8.17 uptime
tomcat@10.10.8.17's password: 
 17:42:17 up 2 days,  5:59,  1 user,  load average: 0.01, 0.06, 0.06
spawn ssh tomcat@10.10.8.16 uptime
tomcat@10.10.8.16's password: 
 17:42:17 up 2 days,  3:14,  1 user,  load average: 0.01, 0.06, 0.05

 [root@bogon exp]# /bin/sh 18_12_2.sh "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
spawn ssh tomcat@10.10.8.16 free -m
tomcat@10.10.8.16's password: 
              total        used        free      shared  buff/cache   available
Mem:           7766         194        7311           9         259        7305
Swap:          7935           0        7935

5、3 案例 3-发送文件

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

#!/usr/bin/expect
if { $argc != 3 } {
        puts "usage: expect $argv0 file host dir"
        exit
}
#define var
set file [lindex $argv 0]
set host [lindex $argv 1]
set dir [lindex $argv 2]
set password "填写你的服务器密码"
spawn scp -p22 -rp $file tomcat@$host:$dir
expect {
        "yes/no"        {send "yes\r";exp_continue}
        "*password"     {send "$password\r"}
}
expect eof

[root@bogon exp]# expect 18_13_1.exp yijiananzhuang.sh  10.10.8.17 /home/tomcat/yijiananzhuang
spawn scp -p22 -rp yijiananzhuang.sh tomcat@10.10.8.17:/home/tomcat/yijiananzhuang
tomcat@10.10.8.17's password: 
yijiananzhuang.sh                                                                                 100%    0     0.0KB/s   00:00

5、4 案例 4-批量发送文件

[root@bogon exp]# cat 18_13_2.sh 

#!/bin/sh
if [ $# -ne 2 ]
        then
                echo $"USAGE:$0 file dir"
                exit 1
fi
file=$1
dir=$2
for n in 16 17
do
        expect 18_13_1.exp $file 10.10.8.$n $dir
done

[root@bogon exp]# /bin/sh 18_13_2.sh yijiananzhuang.sh  /home/tomcat/yijiananzhuang
spawn scp -p22 -rp yijiananzhuang.sh tomcat@10.10.8.16:/home/tomcat/yijiananzhuang
tomcat@10.10.8.16's password: 
yijiananzhuang.sh                                                                                 100%    0     0.0KB/s   00:00    
spawn scp -p22 -rp yijiananzhuang.sh tomcat@10.10.8.17:/home/tomcat/yijiananzhuang
tomcat@10.10.8.17's password: 
yijiananzhuang.sh

5、5 案例 5-批量远程执行 shell 脚本

[root@bogon exp]# cat yum.sh 

#!/bin/sh
sudo yum install -y httpd
#source 远程安装
[root@bogon exp]# /bin/sh 18_12_2.sh "source /home/tomcat/yijiananzhuang/yum.sh"

5、6 案例 6-自动化部署 SSH 密钥认证 +ansible 的案例实战

#生成公钥私钥对
[root@bogon exp]# rm -rf  ~/.ssh/*
[root@bogon exp]# ll ~/.ssh/ 
total 0
[root@bogon exp]# ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa > /dev/null 2>&1 
[root@bogon exp]# ll ~/.ssh/ 
total 8
-rw------- 1 root root 668 Apr 29 18:40 id_dsa
-rw-r--r-- 1 root root 600 Apr 29 18:40 id_dsa.pub

#分发公钥

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

#!/usr/bin/expect
if { $argc != 2 } {
        send_user "usage: expect expect.exp file host \n"
        exit
}
#define var
set file [lindex $argv 0]
set host [lindex $argv 1]
set password "填写你的服务器密码"
#exec command
----------#下面这个文件分发,第一次行,第二次执行就报错,用之前记得先删除远程服务器的ssh文件----------
spawn ssh-copy-id -i $file "-p 22 tomcat@$host"
expect {
        "yes/no"        {send "yes\r";exp_continue}
        "*password"     {send  "$password\r"}
}
expect eof

[root@bogon exp]# cat 18_15_2.sh

#!/bin/sh
for n in 16 17
do
        expect 18_15_1.exp ~/.ssh/id_dsa.pub 10.10.8.$n
done


[root@bogon exp]# /bin/sh 18_15_2.sh 

#ssh测试

[root@bogon exp]# chmod +x exec.sh     
[root@bogon exp]# cat exec.sh      

#!/bin/sh
ssh tomcat@10.10.8.16 uptime
ssh tomcat@10.10.8.17 uptime

[root@bogon exp]# /bin/sh exec.sh  
 18:45:30 up 2 days,  4:17,  1 user,  load average: 0.03, 0.05, 0.05
 18:45:30 up 2 days,  7:02,  1 user,  load average: 0.07, 0.07, 0.05

#安装ansible

[root@bogon exp]# yum install epel-release -y
[root@bogon exp]# yum install ansible -y

#由于现在使用的是普通用户tomcat,那么需要加入ansible_ssh_user=tomcat,不加默认root用户,会导致不能成功执行后续的ansible命令。
[root@bogon ansible]# cat /etc/ansible/hosts
[tomcat]
10.10.8.16 ansible_ssh_user=tomcat
10.10.8.17 ansible_ssh_user=tomcat

[root@bogon exp]# ansible tomcat -m command -a "uptime"

6、其他

在我的这篇博文"## 推送文件(expect交互式方式与sshpass非交互式方式)"也可以参考。


标题:expect自动化交互式程序应用实践
作者:yazong
地址:https://blog.llyweb.com/articles/2020/04/30/1588255663573.html