1. 介绍
expect是建立在tcl(参见:Tcl/Tk快速入门)基础上的一个工具,它可以让一些需要交互的任务自动化地完成。相当于模拟了用户和命令行的交互操作。
一个具体的场景:远程登陆服务器,并执行命令
登录时输入密码需要交互,bash脚本无法完成,可以使用expect来完成。
2. 安装
下面介绍两种安装方式
yum 安装
yum install -y expect
- 1
- 2
源码编译安装
expect 依赖于 tcl,所以需要首先安装 tcl。可以使用rpm检查是否已经安装tcl:
rpm -qa | grep tcl
- 2
如果已安装,则会打印出tcl软件信息
安装过程参考:linux expect 安装http://www.cnblogs.com/daojian/archive/2012/10/10/2718390.html
tcl 地址:https://sourceforge.net/projects/tcl/files/Tcl/选择一个版本
expect 地址:https://sourceforge.net/projects/expect/files/Expect/选择一个版本
注意:wget 下载的时候需要加上 –no-check-certificate,不检查网站证书
3. 原理与工作机制
首先使用 spawn 开启一个会话,然后使用 expect-send 对来执行交互式操作。
spawn 后面跟上一个命令操作,表示开启一个会话。expect 等待输出特定的字符串(通常是提示符),然后使用send 发送交互字符串。比如:
spawn ssh username@host # 远程登录 expect "*assword" # 提示为:"username@host's password:",等待用户输入密码 send "${password}\r" # 这时使用send模拟用户输入密码的字符串,完成登录验证
- 2
- 3
- 4
- 5
4. 基本语法介绍
脚本解释器
脚本中首先引入文件,表明使用的是哪一个shell
#!/usr/bin/expect
- 2
set
设置会话超时时间为30s,若不限制超时时间则应设置为-1
set timeout 30
- 2
set 还可以设置变量
# 使用变量语句:$param 或者 ${param}({}用来避免param和后面的字符串拼接起来导致错误) set param "param_str" set param 1
- 4
spawn
spawn 后面跟一个命令,开启一个会话
spawn ${cmd} # for example : spawn su root
- 2
expect - send
expect 接收命令执行后的输出,然后和期望字符串匹配,若对应这执行相应的send来发送交互信息。
expect "$case1" {send "$respond1\r"} # 这一行等同于下面两行 expect "$case1" send "$response1\r"
- 5
expect 可以有多个分支,就像switch语句一样。
expect { "$case1" {send "$response1\r"} "$case2" {send "$response2\r"} "$case3" {send "$response3\r"} }
- 5
- 6
- 7
结束符
expect eof :等待执行结束,若没有这一句,可能导致命令还没执行,脚本就结束了
interact : 执行完成后保持交互状态,这时可以手动输入信息
注:expect eof 与 interact 二选一即可
接收参数
参数存在argv中,使用第一个参数如下:
set param0 [lindex $argv 0]
- 2
$argc表示参数个数,判断语句如下:
if {$argc < 1} { #do something send_user "usage: $argv0 <param1> <param2> ... " exit }
- 6
注:$argv0 是脚本名,但[lindex$argv 0]是第一个参数 param1,[lindex $argv 1]是第二个参数 param2,以此类推
send_user 用来显示信息到父进程(一般为用户的shell)的标准输出。
5. 实例
实现远程登录服务器,并切换到root用户下执行关闭防火墙的命令,然后退出
#!/usr/bin/expect if {$argc < 4} { #do something send_user "usage: $argv0 <remote_user> <remote_host> <remote_pwd> <remote_root_pwd>" exit } set timeout -1 set remote_user [lindex $argv 0] # 远程服务器用户名 set remote_host [lindex $argv 1] # 远程服务器域名 set remote_pwd [lindex $argv 2] # 远程服务器密码 set remote_root_pwd [lindex $argv 3] # 远程服务器根用户密码 # 远程登录 spawn ssh ${remote_user}@${remote_host} expect "*assword:" {send "${remote_pwd}\r"} expect "Last login:" # 切换到 root send "su\r" expect "*assword:" {send "${remote_root_pwd}\r"} # 执行关闭防火墙命令 send "service iptables stop\r" send "exit\r" send "exit\r" expect eof
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
将代码保存到 remot_root_command.exp 中,权限改为755,然后执行下面这条命令即可:
./remote_root_command.exp <remote_user> <remote_host> <remote_pwd> <remote_root_pwd>
- 2