现代的Shell对程序提供了最小限度的控制(开始,停止,等等),而把交互的特性留给了用户。 这意味着有些程序,你不能非交互的运行,比如说passwd。 有一些程序可以非交互的运行,但在很大程度上丧失了灵活性,比如说su,ssh等。这表明Linux的工具构造逻辑开始出现问题。Expect恰恰填补了 其中的一些裂痕,解决了在Linux环境中长期存在着的一些问题。
Expect是基于TCL的,作为一个脚本语言,expect能在无需管理员参与的情况下实现自动交互(比如passwd,fsck,telnet等),expect也能用于自动测试一些应用程序。
expect的语法和shell的语法非常相似,它支持函数调用,有while语句,switch语句。
1) expect使用spawn调用其他的执行程序,比如
spawn telnet 218.199.20.98 2600
但是在使用的过程中发现spawn不支持管道和重定向,也就是说对于
ls |more ; mysql -p < update.sql 这样的命令spawn不能正确解析。
解决的办法是把这些命令放到一个shell脚本里面,在用spawn执行这个shell脚本。
2) expect 创建子函数使用proc标志,也即:
proc functionname { parameter1,parameter2 } {
......
}
调用子函数非常简单
functionname $param1 $param2
3) expect 使用expect ,send 组合实现自动交互 ,语法如下:
expect {
"login;" { send "$user\n" }
"passwd:" { send "$passwd\n" }
}
使用send的使用后面的内容不显示给用户,如要显示给用户,应使用send_user
4) 注意点:
1. expect里面基本是都是使用{} 而不是使用(),比如函数参数输入外面应用{},
应该是while { } 而不是 while ( ).
2. { 应和其他符合有空格, expect { 正确,expect{ 就会报错.
3. spawn 不支持管道和重定向.
5)一个例子:su的非交互
脚本文件:exp_su.sh
proc do_console_login {pass} {
set timeout 5
set done 1while { $done } {
expect {
"Password:" {
send "$pass\n"
}
eof {
set done 0
}
}
}
}if {$argc<1} {
puts stderr "Usage: $argv0 password.\n "
exit 1
}set PASS [lindex $argv 0]
spawn /tmp/ss
do_console_login $PASS
注意:/tmp/ss是重新写的一个脚本,因为spawn不能识别带参数的命令。其内容如下:
/bin/su - $user -c "/bin/ls /home/$user"
调用方法是: expect exp_su.sh 123456(即密码)