expect用法摘要
时间:2007-04-13 来源:ima
原文见 expect 教程中文版
Expect被设计成专门针和交互式程序的交互。一个Expect程序员可以写一个脚本来描述程序和用户的对话。
接着Expect 程序可以非交互的运行“交互式”的程序。写交互式程序的脚本和写非交互式程序的脚本一样简单。
Expect还可以用于对对 话的一部分进行自动化,因为程序的控制可以在键盘和脚本之间进行切换。
spawn命令激活一个Unix程序来进行交互式的运行。 send命令向进程发送字符串。expect命令等待进程的某些字符串。
expect支持正规表达式并能同时等待多个字符串,并对 每一个字符串执行不同的操作。expect还能理解一些特殊情况,
如超时和遇到文件尾。
expect patlist1 action1 patlist2 action2.....
#注意:该命令在语意上必须是一行
该命令一直等到当前进程的输出和以上的某一个模式相匹配,或者等
到时间超过一个特定的时间长度, 或者等到遇到了文件的结束为止。
如果最后一个action是空的,就可以省略它。
每一个patlist都由一个模式或者模式的表(lists)组成。
如果有一个模式匹配成功,相应的action就被执行。执 行的结果从expect返回。
被精确匹配的字符串(或者当超时发生时,已经读取但未进行匹配的字符串)被存贮在变量expect_match里面。
如 果patlist是eof或者timeout,则发生文件结束或者超时时才执行相应的action.
一般超时的时值是10秒,但可以用类似 "set timeout 30"之类的命令把超时时值设定为30秒。
模式是通常的C Shell风格的正规表达式。模式必须匹配当前进程的从上一个expect或者interact开始的所有输 出(所以统配符*使用的非常)的普遍。但是,
一旦输出超过2000个字节,前面的字符就会被忘记,这可以通过设定 match_max的值来改变。
字符可以使用反斜杠来单独的引用,反斜杠也被用于对语句的延续,如果不加反斜杠的话,语句到一行的结尾处就结 束了。分号可以用于在一行中分割 多个语句。
启动方式
#!/usr/bin/expect
命令行方式
expect -c "set timeout 20;spawn foo;expect"
一旦你把超时时限设置好而且程序启动之后,expect就开始等待文件结束符或者20秒的超时时限。 如果遇
到了文件结束符(EOF),该程序就会停下来,然后expect返回。如果是遇到了超时的情况,expect就返回。在这两
中情况里面,都隐式的杀死了当前进程。
命令
exec sleep 4 "exec" 执行 命令
spawn 开始expect 过程
set 设置变量值
set tt 3
expect 开始模式处理
expect -re 正则表达式模式,结合引用
send 响应
[] 取结果 如[index $argv 2] ,命令序列的结果 [ls]
{}命令组 abort 异常中断
exit n 返回
break ?
interact + 返回用户控制,"+"控制用户的控制行为
close 关闭
wait 等待进程退出
expect_user 等待实际用户输入
send_user 向用户输出
send_error 向标准错误终端输出
内置变量
使用变量方式 a=${b} a= $b
timeout
eof
expect_match 被精确匹配或者在超时前没匹配的串
match_max expect_match的最大长度
argv 输入参数表,$argv[0]为程序本身名字,用 [index $argv n]引用第n个值
spawn_id 当前捕获对象的进程 id,更换该id为当前子进程的其他值,可实现对输出的捕获
逻辑控制
循环语句
for{} {1} {}{do something}
分支语句
set x [ ... ]#依次取a,b的一个可以是 select $a $b
case $x in $a {}
case $x in $b {}
多个spawn 最后一个进程输出被作为expect ,send的对象
if $a 逻辑值
while $bool { ...}
例子 1
单独事务处理
for {} {1} {}{
expect \
eof break \
"*UNREF FILE*CLEAR?" {send "y "} \
"*BAD INODE*FIX?" {send "y "} \
"*?" {interact +} \
}
例子 2
多进程切换
spawn chess ;# start player one
set id1 $spawn_id
expect "Chess "
send "first " ;# force it to go first
read_move
spawn chess ;# start player two
set id2 $spawn_id
expect "Chess "
for {} {1} {}{
send_move
read_move
set spawn_id $id1
send_move
read_move
set spawn_id $id2
}
例子3
多进程切换
spawn tip /dev/tty17 ;# open connection to
set tty $spawn_id ;# tty to be spoofed
spawn login
set login $spawn_id
log_user 0
for {} {1} {} {
set ready [select $tty $login]
case $login in $ready {
set spawn_id $login
expect
{"*password*" "*login*"}{
send_user $expect_match
set log 1
}
"*" ;# ignore everything else
set spawn_id $tty;
send $expect_match
}
case $tty in $ready {
set spawn_id $tty
expect "* *"{
if $log {
send_user $expect_match
set log 0
}
}
"*" {
send_user $expect_match
}
set spawn_id $login;
send $expect_match
}
}
未解决问题: 如何使 spawn ${}形式的命令调用成功