什么是Expect
Expent是基于tcl的相对简单的一个免费的脚本编程工具语言,用来实现自动和交互任务程序进行通信,无需人的手工干预。比如SSH、FTP等,这些程序正常情况都需要手工与它们进行交互,而使用Expect就可以模拟人手工交互的过程,实现自动的和远程的程序交互,从而达到自动化运维的目的。
Expect程序工作流程
Expect的工作流程可以理解为,spawn启动进程 ==> expect期待关键字 ==> send向进程发送字符 ==> 退出结束。
安装Expect软件
首先,配置好yum安装源,并且确保机器可以上网,然后执行yum install expect -y
即可安装Expect软件。
安装完后查看结果:
|
|
先看一个Expect小实例
首先准备3台虚拟机:
|
|
再执行下面例子前,我们先手工执行如下命令
|
|
执行结果:
|
|
Expect 例子脚本内容:
|
|
执行结果:问题:
|
|
问题:
|
|
原因:
- 含有expect的脚本不能用bash执行,bash无法解析。添加可执行权限后,直接./your_script即可
- 这个代码是expect的代码,不由bash解释。
- spawn可以看作expect脚本的内部函数。要第一行改成 #!/usr/bin/expect
Expect语法
Expect中的命令是最重要的部分了,命令的使用语法如下:
|
|
spawn
spawn命令是Expect的初始命令,它用于启动一个进程,之后所有expect操作都在这个进程中进行,如果没有spawn语句,整个expect就无法执行了,spawn使用方法如下:
|
|
在spawn命令后面直接加上要启动的进程、命令等信息,除此之外,spawn还支持其他选项如:
- -open 启动文件进程,具体说明省略。
- -ignore 忽略某些信号,具体说明省略。
expect
使用方法:
|
|
expect命令用于等候一个相匹配内容的输出,一旦匹配上就执行expect后面的动作或命令。这个命令接受几个特有的参数,用的最多的就是-re,表示使用正则表达式的方式匹配,使用起来就像这样:
|
|
从上面的例子可以看出,expect是依附与spawn命令的,当执行ssh命令后,expect就匹配命令执行后的关键字:“password:”,如果匹配到关键字就会执行后面包含在“{}”中的send或exp_send动作,匹配的动作可以放在二行,这样就不需要使用“{}”了,就像下面这样,实际完成的功能与上面是一样的:
|
|
expect命令还有一种用法,他可以在一个expect匹配中多次匹配关键字,并给出处理动作,只需要将关键字放在一个大括号中就可以了,当然还要有exp_continue。
|
|
exp_send和send
在上面的介绍中,我们已经看到exp_send命令的使用,exp_send
命令是expect
中的动作命令,它还有一个完成同样工作的同胞:send,exp_send命令可以发送一些特殊符号,我们看到了\r(回车),还有一些其他的比如:\n、\t等等,这些都与TCL中的特殊符号相同。
|
|
send命令有几个可用参数:
- -i 制定spawn_id,这个参数用来向不同spawn_id的进程发送命令,是进行多程序控制的关键参数。
- -s s代表slowly,也就是控制发送的速度,这个参数使用的时候要与expect中的变量send_slow相关联。
exp_continue
这个命令一般用在动作中,它被使用的条件比较苛刻,看看下面的例子:
|
|
在这个例子中,可以发现exp_continue命令的使用方法,首先它要处于一个expect命令中,然后它属于一种动作命令,完成的工作就是从头开始遍历,也就是说如果没有这个命令,匹配第一个关键字以后就会继续匹配第二个关键字,但有了这个命令后,匹配第一个关键字以后,第二次匹配仍然从第一个关键字开始。
send_user
send_user命令用来把后面的参数输出到标准输出中去,默认的send、exp_send命令都是将参数输出到程序中去的,用起来就像这样:
|
|
这个语句就可以在标准输出中打印Please input password:字符了。
|
|
exit
exit命令功能很简单,就是直接退出脚本,但是你可以利用这个命令对脚本做一些扫尾工作,比如下面这样:
|
|
|
|
Except变量
expect中有很多有用的变量,它们使用方法与TCL语言中的变量相同,比如: set 变量名 变量名 # 设置变量的方法 set $变量名 # 读取变量的方法
|
|
Expect关键字
expect中的特殊关键字用于匹配过程,代表某些特殊含义或状态,一般用于expect族命令中不能在外面单独使用,也可以理解为事件,使用上类似于expect eof {}
eof
eof (end-of-file)关键字用于匹配 结束符,比如文件的结束符、FTP传输停止等情况,在这个关键字后跟上动作来做进一步的控制,特别是FTP交互操作方面,它的动作很大。用一个例子来看看:
|
|
timeout
timeout是expect中的一个重要变量,它是一个全局性的时间控制开关,你可以通过为这个变量赋值来规定整个expect操作时间,注意这个变量是服务于expect全局的,它不会纠缠于某一条命令,即使命令没有任何错误,到时见仍然会激活这个变量,但这个时间到达以后除了激活一个开关之外不会做其他的事情,如何处理是脚本编写人员的事情,看看它的实际使用方法:
|
|
上面的处理中,首先将timeout变量设置为60秒,当出现问题的时候程序可能会停止下来,只要到60秒。就会激活下面的timeout动作,这里我们打印一个信息并且停止了脚步的运行–你可以做更多其他的事情,看自己的意思。
在另一种expect格式中,我们还有一种设置timeout变量的方法,看看下面的例子:
|
|
生产场景Expect实战
|
|
实战1:使用expect实现批量分发/etc/hosts文件
|
|
如果ip很多写循环列表
|
|
测试结果:
|
|
实战2:使用expect批量分发SSH密钥文件
首先准备4台机器:
IP | hostname- |
---|---|
192.168.252.60 | lamp_client |
192.168.252.62 | rsync_client |
192.168.252.63 | nfs_server |
192.168.252.64 | mysql_client |
1 在server端创建公钥与私钥
|
|
2 查看密钥
|
|
3 写批量拷贝脚本
|
|
|
|
|
|
大功告成。
特别提示:如果是禁止了ROOT远程连接,那么就使用普通用户加sudo的方式结合在expect大量分发。有的同学们问,既然做密钥认证了,为什么还要expect分发呢。在做认证期间,第一次的密钥分发,如果机器数量多,比如1000台,就可以expect分发,比ssh-copy-id方式或http的方式都会好一点。
当然从例一可以看出来,即使不用密钥认证,expect依然可以实现分发数据及文件及批量管理部署服务。