一、Expect概述
expect 是基于tcl 演变而来的,所以很多语法和tcl 类似,Expect 是用来进行自动化控制和测试的工具。主要解决shelI脚本中不可交互的问题。对于大规模的linux运维很有帮助
在linux运维和开发中,我们经常需要远程登录服务器进行操作,登录的过程是一个交互的过程,可能会需要输入yes/no,password等信息。为了模拟这种输入,可以使用Expect脚本
Expect安装
yum -y install tcl-devel
yum -y install expect
二、基本命令
-
send
:向进程发送字符串,用于模拟用户的输入, 该命令不能自动回车换行,一般要加\r(回车) -
expect
:
expect的一个内部命令,判断上次输出结果里是否包含指定的字符串,如果有则立即返回,否则就等待超时时间后返回,只能捕捉由spawn启动的进程的输出expect -
spawn
:启动进程,并跟踪后续交互信息 interact:执行完成后保存交互状态,把控制权交给控制台● 单位是:秒 ● timeout -1 为永不超时 ● 默认情况下,timeout是10秒 set timeout 30:设置超时时间为30秒(默认的超时时间是 10 秒,通过 set 命令可以设置会话超时时间, 若不限制超时时间则应设置为-1)
-
exp_continue
:允许expect继续向下执行指令meout:指定超时时间,过期则继续执行后续指令 -
send_user
: 回显命令,相当于echo $argv参数数组:Expect脚本可以接受从bash传递的参数,可以使用
[lindex $argv n] 获得,n从0开始,分别表示第一个$1,第二个$2,第三个 3 … … 参 数 ( 3……参数 ( 3……参数(argvn没有空格则表示脚本名称 ; $argv n有空格则代表下标) 一般流程:spawn 启动追踪 —> expect
匹配捕捉关键字 ——> 捕捉到将触发send 代替人为输入指令—> interact /expect eof
Expect脚本必须以interact或expect eof 结束,执行自动化任务通常expect eof就够了 -
expect eof
:是在等待结束标志。由spawn启动的命令在结束时会产生一个eof标记,expect eof 即在等待这个标记
示例一
注:该脚本是expect脚本,执行时不可以使用sh,可以直接./文件名.sh或者expect 文件名.sh。
#!/usr/bin/expect -f
puts "本地虚拟机远程登录脚本"
#用户名
set user root
#密码
set passwd root
#终端服务器IP
set host 192.168.52.2
#终端服务器端口
set port 22
spawn ssh -l $user -p $port $host
#在expect语句中,5s后超时,不再作出选择(注 -1 永不超时)
set timeout 5
expect {
"Connection refused" exit
"Name or service not know" exit
#表示匹配到yer/no时就发送字符串yes\n到该进程里
"yes/no" { send "yes\n";exp_continue }
#匹配到password时就发送passwd\n到进程里
"*assword" { send "$passwd\n" }
}
expect "#"
send "df -h\n"
#send "exit\r" #如果使用expect eof结束,程序会自动退出远程登录无需显示执行。
#interact 执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。
#Expect脚本必须以interact或expect eof 结束,执行自动化任务通常expect eof就够了
#interact
expect eof
示例二
#!/bin/bash
#用户名
user=root
#密码
passwd=root
#终端服务器IP
host=192.168.52.2
#终端服务器端口
port=22
/usr/bin/expect <<-EOF
#spawn开启一个会话
puts "$passwd\r"
spawn ssh -l $user -p $port $host
#在expect语句中,5s后超时,不再作出选择(注 -1 永不超时)
set timeout 5
expect {
"Connection refused" exit
"Name or service not know" exit
#表示匹配到yer/no时就发送字符串yes\n到该进程里
"yes/no" { send "yes\n";exp_continue }
#匹配到password时就发送passwd\n到进程里
"*assword" { send "$passwd\n" }
}
expect "#"
send "df -h\n"
expect eof
EOF