[toc]
expect自动化交互式程序
1.expect简介
什么是expect
- expect是一个用来实现自动交互功能的软件套件(expect is a software suite for automating interactive tools),是基于TCL的脚本编程工具语言,方便学习,功能强大
为什么要使用expect
- linux中执行系统命令或程序时,系统会以交互式的形式要求输入指定的字符串,之后才能继续执行命令,如果在shell脚本中,这样就不能实现脚本完全自动化执行,因此需要用到expect自动化交互
linux交互式操作的场景
#修改用户密码
$ passwd
Changing password for user root.
New password:
#ssh连接服务器
$ ssh root@10.0.0.10
root@10.0.0.10's password:
#生成ssh密钥
ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
expect自动交互工作流程
- spawn启动指定进程--->expect获取期待的关键字--->send向指定进程发送指定字符--->进程执行完毕,退出结束
2.expect简单使用示例
示例:免交互ssh连接服务器
先手动交互ssh连接一台服务器
$ ssh root@10.0.0.33
The authenticity of host '10.0.0.33 (10.0.0.33)' can't be established.
ECDSA key fingerprint is SHA256:wrYIb1Ou6Yjp70e/3Tz9LSkjNBkW9flmmZjN80wwufU.
ECDSA key fingerprint is MD5:34:61:48:e5:71:3c:11:a0:53:ea:73:e9:4c:cd:e0:ea.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.0.0.33' (ECDSA) to the list of known hosts.
root@10.0.0.33's password:
Last login: Sun May 16 23:13:49 2021 from 10.0.0.2
安装expect
yum -y install expect
编辑expect脚本
脚本开头的#!/usr/bin/expect
是脚本开头解析器,和shell类似,表示 程序使用expect解析
#扩展名使用.exp代表是expect脚本
cat >test.exp <<'EOF'
#!/usr/bin/expect
#执行ssh命令 注意开头必须要有spawn,否则无法实现交互
spawn ssh root@10.0.0.31 uptime
#利用expect获取执行上述ssh命令输出的字符串是否为期待的字符串*password,这里的*是通配符
expect "*password"
#当获取到期待的字符串 *password 时,则发送密码 1 给系统,\n是换行
send "1\n"
#处理完毕后结束expect
expect eof
EOF
使用expect
命令执行脚本,因为之前已经ssh连接过了,所以这里就能不需要输入yes连接了
$ expect test.exp
spawn ssh root@10.0.0.31 uptime
root@10.0.0.31's password:
10:29:02 up 44 min, 1 user, load average: 0.00, 0.01, 0.03
这里仅仅是一个简单的不需要输入密码的示例,但是如果没有ssh连接过的话还是需要手动输入第一次连接需要的yes
3.expect程序自动交互的重要命令
3.1 spawn命令
在expect自动交互程序执行的过程中,spawn
命令是一个开始就需要使用的命令,通过spawn
执行一个命令或程序,之后所有的expect操作都会在这个执行过的命令或程序进程中进行,包括自动交互功能,因此如果没有spawn
命令,expect程序将会无法实现自动交互
语法
spawn [选项] [需要自动交互的命令或程序]
示例
在spawn
命令的后面,直接挤上要执行的命令或程序
spawn ssh root@10.0.0.100 uptime
使用spawn
命令是expect程序实现自动交互工作流程中的第一步,也是最关键的一步
3.2 expect命令
3.2.1 expect命令说明
在expect自动交互程序的执行过程中,当使用spawn
命令执行一个命令或者程序之后,会提示某些交互式信息,expect
命令的作用就是获取spawn
命令执行后的信息,查看是否和其事先自定的相匹配,一旦匹配上指定的内容就执行expect后面的动作,expect命令也有一些选项,相对用的多的是-re
,表示使用正则表达式的方式来匹配
语法
expect 表达式 [动作]
示例
⚠️以下命令不能在命令行中执行,需要放入expect脚本中执行
spawn ssh root@10.0.0.100 uptime
expect "*password" (send 1\r)
3.2.2 expect命令实践
3.2.2.1 实践示例1
执行ssh命令远程获取服务器负载值和eth0网卡,并自动输入yes
及用户名密码
编辑expect脚本
cat >test.exp << 'EOF'
#!/usr/bin/expect
spawn ssh root@10.0.0.100 uptime && ip a s eth0
#起始大括号前要有空格
expect {
"yes/no" {exp_send "yes\r";exp_continue}
"*password" {exp_send "1\r"}
}
expect eof
EOF
说明
-
exp_send
和send
类似,后面的\r(回车)
,和前文的\n(换行)
类似 -
expect {}
,类似多行expect
-
匹配多个字符串,需要在每次匹配并执行动作后,加上
exp_continue
执行脚本
$ expect test.exp
spawn ssh root@10.0.0.31 uptime && ip a s eth0
The authenticity of host '10.0.0.31 (10.0.0.31)' can't be established.
ECDSA key fingerprint is SHA256:o9tdhhhgM3KPZytcz16k/Wt6gfEkDp1FCD3Q7VmLnoE.
ECDSA key fingerprint is MD5:0e:a2:0c:a6:42:e4:95:b4:77:44:14:36:ba:11:2b:d8.
#可以看到这里expect会自动输入yes
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.0.0.31' (ECDSA) to the list of known hosts.
#expect自动输入密码
root@10.0.0.31's password:
10:32:18 up 8:45, 1 user, load average: 0.08, 0.03, 0.05
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:1c:42:1b:e4:d7 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.31/24 brd 10.0.0.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::21c:42ff:fe1b:e4d7/64 scope link
valid_lft forever preferred_lft forever
3.2.2.2 实践示例2
利用expect相应shell脚本中的多个read读入
编辑shell脚本
cat > read.sh <<'EOF'
#!/usr/bin/env bash
read -p "please input your username:" name
read -p "please input your password:" pwd
read -p "please input your email:" mail
echo -n "your name is $name,"
echo -n "your password is $pwd,"
echo "your email is $mail."
EOF