expect是一个基于Tcl的用于自动化交互式命令行程序的工具。它包括expect程序和libexpect程序包。
一个常见的应用场景,比如自动登录某台机器并执行命令:
spawn telnet $remote_server ; # 启动外部程序 expect "username:" ; # 等待匹配字符串 "username" send "$my_user_id\r" ; # 模拟用户输入用户名 expect "password:" ; # 等待输入密码提示 send "$my_password\r" ; # 输入登录密码 expect "%" ; # 等待出现命令行提示符 send "$my_command\r" ; # 输入要执行的命令 expect "%" ; # 等待命令执行结束,出现命令提示符 set results $expect_out(buffer) ; # 获得外部程序的所有输出 send "exit\r" ; # 输入exit退出外部程序 expect eof ; # 等待外部程序退出
Expect其实是一个提供了扩展的Tcl程序。它在支持Tcl内置的命令的同时,提供了一组新的命令用于控制外部进程。
expect 很像Tcl内置的switch命令,可以同时指定多个匹配字符串和匹配格式。
expect { "pattern*" {...} -gl "pattern*" {...} -re "pattern.*" {...} -ex "pattern* {...} }
-gl
选项-re
用来指定使用正则表达式匹配(regexp)-ex
用来指定使用完全匹配,即要求与指定的模式完全一样timeout
是内置的特殊模式,用于匹配超时的情况。eof
这个内置的特殊模式,用于匹配EOF,通常是外部命令结束default
匹配timeout
或者eof
如果没有指定timeout
模式,则超时的情况下,执行的默认命令为空,即什么都不做。
超时的设置默认是10秒钟。可以通过全局变量timeout
来改变超时时间。设置为"-1"的时候则无限等待。
用expect与Shell交互的一个常见问题是不同用户的命令行提示符(prompt)可能会很不一样。
比如可能看起来像下面这样
[223]root@cyborg:/usr/local/etc>
,81 myhost >
[user@host ~]$
一个常见的做法是用正则表达式去匹配
set prompt {[\r\n]?[^\r\n]+[%#>\$] ?$} expect { -regexp $prompt { puts "Match" } timeout { puts "timeout" } }