spawn
激活一个Unix程序来进行交互式的运行。expect
等待进程的某些字符串。send
向进程发送字符串。
expect
支持逐个顺序匹配(串行匹配)和同时匹配多个模式(并行匹配)
串行匹配
每条expect 都是阻塞式等待,只有前一条匹配并执行完成后,才执行下一条
spawn sudo passwd root
expect { "password for" { send "your_sudo_password\r" } } # 这种形式可以匹配多个模式,这里只有一个模式
# 下面是两条单独的命令,不管expect是否匹配成功(是否超时),都会执行 send 命令
expect "New password:"
send "123456\r"
expect "Retype new password:" { send "123456\r" } # 匹配单个模式
# 等待 spawn 启动的子进程结束
expect eof
并行匹配
所有模式同时监听,哪个先出现就先匹配
exp_continue
会让 expect 继续监听,如果没有exp_continue
,当匹配到了该项,执行对应动作后就会退出整个 expect 语句。
spawn sudo passwd root
expect {
"password for" { send "your_sudo_password\r"; exp_continue }
"New password:" { send "123456\r"; exp_continue }
"Retype new password:" { send "123456\r"; exp_continue }
eof
}
set timeout <秒数>
,不设置默认10s
set timeout -1
永远等待,直到有输出
如果超时了,并且有timeout
分支,则会执行timeout
分支的代码,如果没有timeout
分支,则会报错,继续执行。
可以在某一处局部设置 timeout
set timeout 3 # 会一直生效,直到再次调用 set timeout 修改它
expect {
"Username:" { send "admin\r" }
timeout { puts "用户名超时"; exit 1 }
}
set timeout 10
expect {
"Password:" { send "pass\r" }
timeout { puts "密码超时"; exit 1 }
}
send
命令只是把命令文本发送给目标程序的标准输入(就像人在终端键盘上输入回车那样),它:
- 不会等待命令执行完成
- 不会等待输出
- 不会阻塞脚本流程
即使 expect
因为超时退出了,被 spawn
启动的命令通常仍会在后台继续运行
eof
是对 spawn 启动的程序是否退出 的检查
在 expect
中,默认是部分匹配(substring match),不是全匹配。
-re
使用正则匹配
-exact
精确匹配
默认是 glob(类似 shell 通配符)匹配
匹配模式中的特殊字符
*
[]
?
\
expect -exact "pattern"
精确匹配整个字符串,不做任何特殊字符解析。
-exact
后面不能带花括号块 {}
来做多模式匹配,它只能匹配一个具体字符串
匹配模式可以选择使用{ }
括起来而不是使用" "
,从而避免 Tcl 提前对字符串做出解释