Shell编程之Expect免交互
Expect概述
Expect安装
Expect基本命令
Expect执行方式
Expect案例
Expect概述
Expect
Expect
是建立在tcl
基础上的一个工具,Expect
是用来进行自动化控制和测试的工具。主要解决shell
脚本中不可交互的问题。对于大规模的linux
运维很有帮助- 在
linux
运维和开发中,我们经常需要远程登录服务器进行操作,登录的过程是一个交互的过程,可能会需要输入yes/no password
等信息。为了模拟这种输入,可以使用Expect
脚本
Expect安装
挂载光盘
制作本地YUM源
执行安装命令
[root@localhost ~]# yum install expect -y
已加载插件:fastestmirror, langpacks
base | 3.6 kB 00:00:00
extras | 2.9 kB 00:00:00
updates | 2.9 kB 00:00:00
(1/4): extras/7/x86_64/primary_db | 152 kB 00:00:00
(2/4): base/7/x86_64/group_gz | 165 kB 00:00:00
(3/4): updates/7/x86_64/primary_db | 1.9 MB 00:00:01
...//省略部分内容...
正在安装 : 1:tcl-8.5.13-8.el7.x86_64 1/2
正在安装 : expect-5.45-14.el7_1.x86_64 2/2
验证中 : 1:tcl-8.5.13-8.el7.x86_64 1/2
验证中 : expect-5.45-14.el7_1.x86_64 2/2
已安装:
expect.x86_64 0:5.45-14.el7_1
作为依赖被安装:
tcl.x86_64 1:8.5.13-8.el7
完毕!
Expect基本命令
send:向进程发送字符串,用于模拟用户的输入
expect
expect
的一个内部命令,判断上次输出结果里是否包含指定的字符串,如果有则立即返回,否则就等待超时时间后返回。- 只能捕捉由
spawn
启动的进程的输出
spawn:启动进程,并跟踪后续交互信息
interact:执行完成后保持交互状态,把控制权交给控制台
Timeout:指定超时时间,过期则继续执行后续指令
- 单位是:秒
timeout -1
为永不超时- 默认情况下,
timeout
是10
秒
exp_ continue
send_ user
$argv参数数组
Expect
脚本可以接受从bash
传递的参数.可以使用[lindex $argv n]
获得,n
从0
开始,分别表示第一个,第二个,第三个…参数
Expect脚本必须以interact或expect eof结束,执行自动化任务通常expect eof就够了
expect eof
是在等待结束标志。由spawn
启动的命令 在结束时会产生一个eof
标记,expect eof
御在等待这个标记
Expect语法
单一分支语法
expect "password:" {send "mypassword\r";}
多分支模式语法
expect "aaa" {send"AAA\r"} //send命令不具备回车换行功能,一般要加\r或\n
expect "aaa" {send"AAA\r"}
expect "aaa" {send"AAA\r"}
expect {
"aaa" {send "AAA\r"} //只要配置aaa或bbb或ccc中的任何一个,执行相应的send语句后退出该expect语句
"bbb" {send "BBB\r"}
"ccc" {send "CCC\r"}
}
expect {
"aaa" {send "AAA";exp_continue} //exp_continue表示继续后面的匹配,如果匹配了aaa,执行
"bbb" {send "BBB";exp_continue} 完send语句后还要继续向下匹配bbb
"ccc" {send "CCC"}
}
Expect执行方式
直接执行
- 使用
expect
免交互使用ssh
远程登录另一台服务器,这里我开启两台Linux
服务器。
[root@localhost ~]# vim demo19.sh //编辑脚本文件
#!/usr/bin/expect //expect二进制文件路径
set timeout 5 //超时时间
log_file tast.log //记录日志文件存放位置
log_user 1 //一个用户
set hostname [lindex $argv 0] //设定第一个位置参数传递并设置变量名hostname
set password [lindex $argv 1] //设定第二个位置参数传递并设置变量名password
spawn ssh root@$hostname //追踪命令
expect { //使用expect命令捕捉条件,设定输入信息,进行免交互设置
"(yes/no)" //设定匹配条件
{send "yes\r";exp_continue} //条件匹配并输入内容,并继续向下匹配
"*password" //设定匹配条件
{send "$password\r"} //条件匹配,引用位置变量输入信息
}
interact //完成后将控制权交给控制台
[root@localhost ~]# chmod +x demo19.sh //给脚本文件添加执行权限
[root@localhost ~]# ./demo19.sh 192.168.144.135 123123 //执行脚本
spawn ssh root@192.168.144.135
The authenticity of host '192.168.144.135 (192.168.144.135)' can't be established.
ECDSA key fingerprint is SHA256:B8IsZOFG7FbtVkIK+dMILmo0iA4OEIeVGY0GnnCbXhk.
ECDSA key fingerprint is MD5:c2:d8:09:17:de:6e:ec:07:06:1b:ac:b6:1e:bd:62:09.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.144.135' (ECDSA) to the list of known hosts.
root@192.168.144.135's password:
Last login: Sun Oct 13 23:29:38 2019 from 192.168.144.1 //自动登录服务器
[root@localhost ~]# ifconfig //查看服务器IP地址
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.144.135 netmask 255.255.255.0 broadcast 192.168.144.255 //成功登录
inet6 fe80::a85a:c203:e2e:3f3c prefixlen 64 scopeid 0x20<link>
inet6 fe80::ad78:663f:1f02:22e4 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:75:9f:c8 txqueuelen 1000 (Ethernet)
...//省略部分内容...
嵌入执行
[root@localhost ~]# vim demo20.sh //编辑脚本文件
#!/bin/bash
hostname=$1 //设置位置参数变量
password=$2
/usr/bin/expect <<-EOF //加载expect功能,EOF前面加“-”是为增加容错性,-EOF 前面的“-"只能容错制表
spawn ssh root@$hostname 符,不能容错空格
expect {
"(yes/no)"
{send "yes\r";exp_continue} //进行免交互配置
"*password"
{send "$password\r"}
}
expect "*]#" //捕捉内容结尾为“]#”的内容
send "exit\r" //匹配后输入exit退出登录
expect eof //等待结束标志
EOF //结束标志
[root@localhost ~]# chmod +x demo20.sh //添加执行权限
[root@localhost ~]# ./demo20.sh 192.168.144.135 123123 //执行脚本,并输入位置变量
spawn ssh root@192.168.144.135
root@192.168.144.135's password:
Last login: Sun Oct 13 23:58:05 2019 from 192.168.144.1
[root@localhost ~]# exit
登出
Connection to 192.168.144.135 closed.
[root@localhost ~]# ifconfig //查看IP地址信息
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.144.133 netmask 255.255.255.0 broadcast 192.168.144.255
inet6 fe80::a85a:c203:e2e:3f3c prefixlen 64 scopeid 0x20<link> //成功登出
ether 00:0c:29:5b:d3:a0 txqueuelen 1000 (Ethernet)
RX packets 11058 bytes 855440 (835.3 KiB)
...//省略部分内容...