Shell Expect自动化交互
Expect是建立在tcl基础上的一个工具,Expect是用来自动化控制和测试的工具。主要解决shell脚本中不可交互的问题。有助于大规模的系统运维工作。在日常的运维与开发中,常常需要运城登录到服务器,然而登录的过程却是个需要交互的过程,可能会要输入yes/no等信息,使用Expect脚本即可实现免交互操作。
expect是一个工具,所以需要进行安装
rpm -q expect
rpm -q tcl
yum -y install expect
1、基本命令
1.1 脚本解释器
expect脚本中首先引入文件,表明使用的是哪一个shell
#!/usr/bin/expect
1.2 spawn
spawn后面通常跟一个Linux执行命令,表示开启一个会话、启动进程,并追踪后续交互信息。
例:
spawn passwd root
1.3 expect
判断上次输入结果中是否包含指定的字符串,如果有则立即返回,否则就等待超时时间后返回:只能捕捉由spawn启动的进程的输出;用于接收命令执行后的输出,然后和期望的字符串匹配
1.4 send
向进程发送字符串,用于模拟用户的输入;该命令不能自动回车换行,一般要加\r(回车)或者\n
例:
方式一:
expect "密码"{ send "abc123\r"}
方式二:
expect"密码"
send "abc123\r"
方式三:
expect支持多个分支
expect
"密码1"{ send "abc123\r"}
"密码2"{ send "123456\r"}
"密码3"{ send "123123\r"}
1.5 结束符expect eof/interact
expect eof
表示交互结束,等待执行结束,退回到原用户,与spawn对应。比如切换到root用户,expect脚本默认的是等待10s,当执行完命令后,默认停留10s后,自动切回了原用户
interact 执行完成后保持交互状态,把控制权交给控制台,会停留在目标终端而不会退回到原终端,这个时候就可以手工操作了,interact后的命令不起作用,比如interact后添加exit,并不会退出root用户。而如果没有interact则登录完成后会退出,而不是留在远程终端上。使用interact会保持在终端而不会退回到原终端,比如切换到root用户,会一直在root用户状态下;比如ssh到另一服务器,会一直在目标服务器终端,而不会切回的原服务器。
注意: expect eof 与 interact只能二选一。
1.6 set
expect 默认的超时时间是10秒,通过 set 命令可以设置会话超时时间,若不限制超时时间则应设置为-1。
例如:set timeout 20 // 表示会话超时时间为20s
1.7 exp_continue
exp_continue 附加于某个expect判断项之后,可以使该项被匹配后,还能继续匹配该expect-判断语句内的其他项。exp_continue类似于控制语句中的 continue 语句。表示允许expect继续向下执行指令。
以修改用户密码为例,因为交互是需要输入两次密码用于确认密码的正确性,在第一次输入后,需要输出第二次的密码。
spawn passwd
expect
{
"新的 密码"{send "123456/r";exp_continue;}
"重新输入"{send "123456/r";}
}
注意:使用exp continue时,如果跟踪像passwd 这样的输入密码后就结束进程的命令,expect{}外不要再加上expect eof,因为spawn进程结束后会默认向expect发送eof,会导致后面的 expect eof执行报错
1.8 send_user
send_user 表示回显命令,相当于echo
1.9 接收参数
expect脚本可以接受从bash命令行传递的参数,使用 [ lindex $argv n ] 获得。其中n从0开始,分别表示第一个,第二个,第三个…参数。例:
set hostname [ lindex $argv 0]
相当于hostname=$1
set password [ lindex $argv 1]
相当于password=$2
2、编辑expect脚本
2.1 定义和引用变量
用set关键字定义变量,变量名和变量的值中间用空格分开,其他用法与shell脚本一致
例题:引用位置变量
#!/usr/bin/expect
set password [lindex $argv 0]
spawn passwd test2
expect "新的*"
send "${password}\r"
expect "重新*"
send "${password}\r"
expect eof
2.2 嵌入执行模式,将expect过程融入Shell当中,方便执行和处理
例:免交互创建用户并设置密码
方式一:
#!/bin/bash
user=$1
password=$2
useradd $user
/usr/bin/expect <<-EOF
spawn passwd $user
expect "新的*"
send "${password}\r"
expect "重新*"
send "${password}\r"
expect eof
EOF
方式二:
#!/bin/bash
user=$1
password=$2
useradd $user
/usr/bin/expect <<-EOF
spawn passwd $user
expect {
"新的*"
{send "${password}\r";exp_continueinue}
"重新*"
{send "${password}\r";}
expect eof
}
EOF
例题:对sdb磁盘进行划分区域并挂载在/test目录下。
方式一:
#!/bin/bash
/usr/bin/expect <<-EOF
spawn fdisk /dev/sdb
expect "命令(输入 m 获取帮助):"
send "n\r"
expect "Select (default p):"
send "p\r"
expect "分区号"
send "\r"
expect "起始 扇区"
send "\r"
expect "Last 扇区, +扇区 or +size{K,M,G}"
send "\r"
expect "命令"
send "w\r"
expect eof;
EOF
mkfs.xfs -f /dev/sdb1 >/dev/null
mount /dev/sdb1 /test >/dev/null
mount -a
3、总结
在嵌入执行模式时,可以使用expect{捕获信息}和expect 捕获信息,但是expect是一个循环,如果捕获的内容中存在两个相同的内容,则会出现死循环(执行原理就是自命令向下执行,捕获内容相同执行send发送输入内容,如果出现捕获的内容中有两个相同的,则会匹配第一个匹配上的)。
非嵌入expect脚本,使用的expect进行解释,所以不能使用sh,bash等命令执行脚本,否会报找不到命令的错误。所以只能使用相对路径或绝对路径执行。
|