一、Expect简介
1.什么是Expect?
Expect是一个用来实现自动交互功能的软件套件,是基于TCL(Tool Command Language)的脚本编程工具语言。
2.使用场景及运行流程
(1)使用场景
需要模拟手工交互的所有过程,实现自动与远端程序的交互,达到自动化运维的目的。
(2)运行流程
spawn启动指定进程;
expect获取关键字;
send向指定进程发送指定字符;
exit进程执行完毕,退出结束。
二、Linux安装Expect软件
rpm -qa expect
yum -y install expect
三、使用Expect实现SSH自动交互,并查看网卡信息
1.spawn命令
作用:通过执行一个命令或程序,实现自动交互工作。
语法:spawn 【选项】 【命令或程序】
选项:-open 启动文件进程 -ignore 忽略警告信号
2.expect命令
作用:获取spawn命令执行后的信息,并匹配;
若匹配指定的内容,则执行后面的动作。
语法: expect 表达式 【动作】
如:
expect "*password" {send "123456\r"}
3.SSH自动交互脚本
#查看expect命令位置
[root@localhost ~]# which expect
/bin/expect
#编写SSH自动交互脚本
[root@localhost ~]# vim ssh.exp
#!/bin/expect
spawn ssh root@192.168.189.130 ifconfig ens33
expect "*password"
send "123456\n"
expect eof
#执行脚本
[root@localhost ~]# expect ssh.exp
spawn ssh root@192.168.189.130 ifconfig ens33
root@192.168.189.130's password:
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.189.130 netmask 255.255.255.0 broadcast 192.168.189.255
inet6 fe80::20c:29ff:fecb:ee45 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:cb:ee:45 txqueuelen 1000 (Ethernet)
RX packets 27138 bytes 10143859 (9.6 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 4663 bytes 561986 (548.8 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
#效果:无需手工输入密码,并可以登录130服务器,显示网卡信息
四、Expect常用命令
1.send命令:匹配指定字符串,发送指定字符串给系统
实例:自动输入个人信息
#编写模拟输入信息的脚本
[root@localhost ~]# vim read.sh
#!/bin/bash
read -p 'Please input your username:' name
read -p 'Please input your password:' pass
read -p 'Please input your email:' mail
echo -n "Your name is $name,"
echo -n "Your password is $pass,"
echo -n "Your email is $mail."
echo -e "\n"
#用send命令发送相应信息
[root@localhost ~]# vim send.exp
#!/bin/expect
spawn /bin/bash read.sh
expect {
"username" {exp_send "zhangsan\r";exp_continue}
"*pass*" {send "123456\r";exp_continue}
"*mail*" {exp_send "a@qq.com\r"}
}
expect eof
#执行脚本
[root@localhost ~]# expect send.exp
spawn /bin/bash read.sh
Please input your username:zhangsan
Please input your password:123456
Please input your email:a@qq.com
Your name is zhangsan,Your password is 123456,Your email is a@qq.com.
#效果:自动发送相关字符串给脚本,并打印信息
2.exp_continue命令:让expect程序继续匹配,应用于不同动作的匹配
实例:同上
3.send_user命令:负责打印Expect脚本信息,类似shell里的echo
[root@localhost ~]# vim user.exp
#!/bin/expect
send_user "My name is zhangsan.\n"
send_user "I'm 24 years old.\n"
#执行脚本
[root@localhost ~]# expect user.exp
My name is zhangsan.
I'm 24 years old.
#存在echo -e功能
4.exit命令:负责退出Expect脚本;退出前可以执行一些清理或提示的命令
[root@localhost ~]# vim exit.exp
#!/bin/expect
send_user "My name is zhangsan.\n"
send_user "I'm 24 years old.\n"
exit -onexit {
send_user "Good bye.\n"
}
#执行脚本
[root@localhost ~]# expect exit.exp
My name is zhangsan.
I'm 24 years old.
Good bye.
五、生产环境下的Expect案例
1.环境准备
IP | 主机名 | 角色 |
---|---|---|
192.168.189.128 | server | master |
192.168.189.131 | bbs | slave 1 |
192.168.189.132 | web02 | slave 2 |
2.案例一:批量执行命令
#实现Expect自动交互
[root@localhost ~]# vim command.exp
#!/bin/expect
if { $argc != 2 } {
puts "usage:expect $argv0 ip command"
exit
}
set ip [lindex $argv 0]
set cmd [lindex $argv 1]
set password "123456"
spawn ssh root@$ip $cmd
expect {
"yes/no" {send "yes\r";exp_continue}
"*password" {send $password\r}
}
expect eof
#master本机测试该脚本
[root@localhost ~]# expect command.exp 192.168.189.128 uptime
spawn ssh root@192.168.189.128 uptime
root@192.168.189.128's password:
16:57:21 up 2:00, 1 user, load average: 0.00, 0.01, 0.05
[root@localhost ~]# expect command.exp 192.168.189.128 "free -m"
spawn ssh root@192.168.189.128 free -m
root@192.168.189.128's password:
total used free shared buff/cache available
Mem: 1980 1008 209 20 762 698
Swap: 2046 0 2046
#利用shell循环执行Expect命令
[root@localhost ~]# vim for_command.sh
#!/bin/bash
if [ $# -ne 1 ]
then
echo $"USAGE:$0 cmd"
exit 1
fi
cmd=$1
for n in 128 131 132
do
expect command.exp 192.168.189.$n "$cmd"
done
#测试批量执行命令
[root@localhost ~]# sh for_command.sh "ifconfig ens33"
spawn ssh root@192.168.189.128 ifconfig ens33
root@192.168.189.128's password:
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.189.128 netmask 255.255.255.0 broadcast 192.168.189.255
inet6 fe80::20c:29ff:feab:69ca prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:ab:69:ca txqueuelen 1000 (Ethernet)
RX packets 6125 bytes 423040 (413.1 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1741 bytes 210313 (205.3 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
spawn ssh root@192.168.189.131 ifconfig ens33
root@192.168.189.131's password:
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.189.131 netmask 255.255.255.0 broadcast 192.168.189.255
inet6 fe80::65e6:4179:6028:e880 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:cb:18:54 txqueuelen 1000 (Ethernet)
RX packets 72 bytes 8567 (8.3 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 73 bytes 8173 (7.9 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
spawn ssh root@192.168.189.132 ifconfig ens33
root@192.168.189.132's password:
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.189.132 netmask 255.255.255.0 broadcast 192.168.189.255
inet6 fe80::4ebd:38c0:6749:ca9c prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:51:8e:f1 txqueuelen 1000 (Ethernet)
RX packets 68 bytes 8455 (8.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 91 bytes 11431 (11.1 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@localhost ~]# sh for_command.sh uptime
spawn ssh root@192.168.189.128 uptime
root@192.168.189.128's password:
17:05:21 up 2:08, 1 user, load average: 0.10, 0.05, 0.06
spawn ssh root@192.168.189.131 uptime
root@192.168.189.131's password:
17:05:21 up 3 min, 0 users, load average: 0.09, 0.28, 0.14
spawn ssh root@192.168.189.132 uptime
root@192.168.189.132's password:
17:05:24 up 3 min, 0 users, load average: 0.46, 0.79, 0.38
3.案例二:批量发送文件
#实现Expect自动交互
[root@localhost ~]# vim file.exp
#!/bin/expect
if { $argc !=3 } {
puts "usage:expect $argv0 file host dir"
exit
}
set file [lindex $argv 0]
set host [lindex $argv 1]
set dir [lindex $argv 2]
set password "123456"
spawn scp -P22 -rp $file root@$host:$dir
expect {
"yes/no" {send "yes\r";exp_continue}
"*password" {send "$password\r"}
}
expect eof
#master本机测试该脚本
[root@localhost ~]# expect file.exp read.sh 192.168.189.131 /tmp
root@192.168.189.131's password:
read.sh 100% 342 129.3KB/s 00:00
#利用shell循环执行Expect命令
[root@localhost ~]# vim for_file.sh
#!/bin/bash
if [ $# -ne 2 ]
then
echo $"USAGE:$0 file dir"
exit 1
fi
file=$1
dir=$2
for n in 128 131 132
do
expect file.exp $file 192.168.189.$n $dir
done
#测试批量执行命令
[root@localhost ~]# sh for_file.sh bbs.exp /tmp
spawn scp -P22 -rp bbs.exp root@192.168.189.128:/tmp
root@192.168.189.128's password:
bbs.exp 100% 107 85.8KB/s 00:00
spawn scp -P22 -rp bbs.exp root@192.168.189.131:/tmp
root@192.168.189.131's password:
bbs.exp 100% 107 64.8KB/s 00:00
spawn scp -P22 -rp bbs.exp root@192.168.189.132:/tmp
root@192.168.189.132's password:
bbs.exp 100% 107 51.1KB/s 00:00
4.案例三:批量执行shell脚本(以安装tree命令为例)
#编写安装tree命令的脚本
[root@localhost ~]# vim yum.sh
yum -y install tree
[root@localhost ~]# chmod +x yum.sh
#发送可执行的脚本文件到所有机器
[root@localhost ~]# sh for_file.sh yum.sh /tmp
#远程连接服务器并执行脚本
[root@localhost ~]# sh for_command.sh "source /tmp/yum.sh"