余苏明的幻想乡

第七 Expect自动化交互式程序

第七 Expect自动化交互式程序

@(shell脚本)[学习]

[toc]

什么是Expect

Expect式一个用来实现自动交互功能的软件套件,是基于TCL的脚本编程工具语言,方便学习,功能强大

Expect程序自动交互的重要命令

spawn命令

语法:

1
2
3
spawn [ 选项 ] [ 需要自动交互的命令或程序 ]
########
spawn ssh root@192.168.33.130 uptime

expect命令

语法:

1
2
3
4
5
expect 表达式 [ 动作 ]
############
spawn ssh root@192.168.33.130 uptime
expect "*password" { send "123456\r" }
# {}内空格不敏感,两端留空格与不留空格一样

expect命令实践:

1
2
3
4
5
#!/usr/bin/expect #<==脚本解释器
spawn ssh root@192.168.33.130 uptime
expect "*password"
send "123456\r"
expect eof #<==想要输出结果,还必须加eof,表示expect结束

说明:

  1. exp_send和send类似
  2. expect{}类似多行expect.
  3. 匹配多个字符串,需要在每次匹配并执行动作后,加上exp_continue。

test.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash
#Author:summingyu
#Blog:https://summingyu.github.io/
#Time:2017-02-23 15:48:09
#Name:test.sh
#Version:V1.0
#Description: This is a test script.
echo "hello,world"
read -p 'Please input your username:' name
read -p 'Please input your password:' pass
read -p 'Please input your username:' name
read -p 'Please input your mail:' mail
echo -n "your name is ${name}."
echo -n "your password is ${pass}"
echo -n "your mail is ${mail}"

test.exp

1
2
3
4
5
6
7
8
#!/usr/bin/expect
spawn /bin/sh test.sh
expect {
"username" { exp_send "123456\r";exp_continue }
"pass" { send "333\n" ;exp_continue}
"mail" { send "333\n"}
}
#expect eof #<==匹配全有exp_continue时加这个会报错

执行expect test.exp结果如下

1
2
3
4
5
6
7
spawn /bin/sh test.sh
hello,world
Please input your username:123456
Please input your password:333
Please input your username:123456
Please input your mail:333
your name is 123456.your password is 333your mail is 333

  1. 如果需要一次匹配多个字符串,那么不同的匹配之间就要加上exp_continue,否则expect将不会自动输入指定的字符串。最后一个的结尾就不需要加上exp_continue了。
  2. 且每次匹配都是会重新匹配,顺序可以不同

例如将匹配脚本test.sh的mail行插入到上面

1
2
3
4
5
6
read -p 'Please input your username:' name
read -p 'Please input your password:' pass
#在这里插入一行mail
read -p 'Please input your mail:' mail
read -p 'Please input your username:' name
read -p 'Please input your mail:' mail

结果如下

1
2
3
4
5
6
spawn /bin/sh test.sh
hello,world
Please input your username:123456
Please input your password:333
Please input your mail:333
Please input your username: #<==在这里停顿!

send_user命令

类似echo -e 打印脚本信息

常用命令总结

expect命令 作用
spawn 一开始使用的命令,通过spawn执行命令,然后所有的expect操作都在这个执行的命令或进程中进行交互
expect 获取交互信息,看是否与实践指定的信息相匹配,匹配则执行指定内容后的动作
send expect中的动作命令,发送指定字符串给系统。还有个类似命令exp_send。
exp_continue 属于一种动作命令,用于多次匹配的动作中,相当于循环的continue
send_user 相当于echo
exit 退出expect脚本

Expect程序变量

普通变量

定义变量语法:
set 变量名 变量值

打印变量语法:
puts $变量名
send_user也可以用于打印输出

特殊参数变量

在Expect中\$argv表示参数数组,可以是用[lindex \$argv n]接收Expect脚本传参。
n从0开始。

但是[lindex \$argv 0]相当于shell里的\$1
set file [lindex $argv 0]获取的是\$1

除了位置参数外,还有其他特殊参数
$argc表示传参的个数,$argv0表示脚本名字

if条件语句

1
2
3
if { 条件表达式 } {
指令
}


1
2
3
4
5
if { 条件表达式 } {
指令
} else {
指令
}

说明:if关键字后面有空格,else关键字前后都有空格,{ 条件表达式 }里面可以没有空格,但外面与指令的大括号相连的地方要有空格

Expect中的关键字

eof关键字

end-of-file。用于匹配结束符。例如文件的结束符,FTP传输停止等情况,在这个关键字后跟上动作来做进一步控制,特别是ftp交互操作方面,它的作用很大。

timeout关键字

timeout是expect中一个控制时间的关键字,全局性的。脚本执行到达规定时间后,会直接执行结尾的timeout动作。
0表示立即超时,-1表示永不超时
在expect{}中还可以使用这个语法

1
2
3
4
5
expect {
-timeout 3
"yes/no" { exp_send "yes\r";exp_continue }
timeout { puts "Request timeout by oldboy.";return }
}