转自:http://www.xmydlinux.org/201109/607.html
1、下载和安装expect
在expect能正常与程序交互之前需安装TCl,下载地址为:http://www.tcl.tk/software/tcltk/
expect建议使用yum或者apt安装。也可到官网下载源码安装。官网地址:http://expect.nist.gov
[root@xmydlinux ~]# yum list |egrep “tcl|expect”
db4-tcl.i386 4.3.29-10.el5_5.2 installed
expect.i386 5.43.0-5.1 installed tcl.i386 8.4.13-4.el5 installed
安装红色标识的两个软件包即可!
2、交互式会话基础
expect命令介绍
spawn:启动一个程序或进程
send:给进程或程序返回结果
expect:接受程序或进程输出
interact:使用户处于进程或程序的交互状态
3、用autoexpect自动创建expect脚本
3.1、一个简单的实例:
随便新建一个提问式shell test.sh如下
#!/bin/bash
echo “吃了吗?”
read REPLY
echo “现在几点了?”
read REPIY
利用autoexpect程序生成自动回答exp文件
[root@mail test]# chmod 777 test.sh
[root@mail test]# autoexpect ./test.sh
autoexpect started, file is script.exp
吃了吗?
还没有 #输入回答部分
现在几点了?
中午12点 #输入回答部分
autoexpect done, file is script.exp
自动应答文件创建完毕。我们过滤掉“#”内容,查看如下。(带说明)
[root@mail test]# grep -v “^#” script.exp |grep -v “^#”
set force_conservative 0
if {$force_conservative} {
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s -- $arg
}
}
set timeout -1
<span style="color: #ff0000;">#设置永不超时</span>
spawn ./test.sh
<span style="color: #ff0000;">#启动test.sh程序</span>
match_max 100000
expect -exact "吃了吗?\r
"
send -- "还没有"
expect -exact "还没有"
send -- "\r"
expect -exact "\r
现在几点了?\r
"
send -- "中午"
expect -exact "中午"
send -- "12点\r"
<span style="color: #ff0000;">#expect部分是捕获到test.sh的输出,而send部分则是给出返回结果。即我们想要的应答</span>
expect eof
<span style="color: #ff0000;">#expect eof为结束符</span></pre>
当然上面内容为autoexpect自动生成,会有很多不需要的说明以及对话方式也不太便于查阅。。我们可以简单将其修改为如下内容:
[root@mail test]# cat test.exp
#!/usr/bin/expect -f
set force_conservative 0
if {$force_conservative} {
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s – $arg
}
}
set timeout -1
spawn ./test.sh
match_max 100000
expect “吃了吗?\r”
send – “还没有 \r”
expect “现在几点了?\r”
send – “中午12点 \r”
expect eof
运行效果如下:
[root@mail test]# ./test.exp
spawn ./test.sh
吃了吗?
还没有
现在几点了?
中午12点
3.2、一个FTP自动交互下载实例:
[root@mail test]# vi ftp.exp
#!/usr/bin/expect -f
set force_conservative 0 ;# set to 1 to force conservative mode even if
;# script wasn't run conservatively originally
if {$force_conservative} {
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s -- $arg
}
}
set timeout -1
spawn ftp 192.168.0.5
match_max 100000
expect "Name *: "
send -- "admin\r"
expect "Password:"
send -- "123\r"
expect "ftp> "
send -- "get JavaService-2.0.10.zip \r"
expect "ftp> "
send -- "bye\r"
expect eof</pre>
运行效果如下:
[root@mail test]# ./ftp.exp
spawn ftp 192.168.0.5
Connected to 192.168.0.5 (192.168.0.5).
220 Serv-U FTP Server v6.3 for WinSock ready…
Name (192.168.0.5:root): admin
331 User name okay, need password.
Password:
230 User logged in, proceed.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> get JavaService-2.0.10.zip
local: JavaService-2.0.10.zip remote: JavaService-2.0.10.zip
227 Entering Passive Mode (192,168,0,5,17,127)
150 Opening BINARY mode data connection for JavaService-2.0.10.zip (203245 Bytes).
226 Transfer complete.
203245 bytes received in 0.018 secs (1.1e+04 Kbytes/sec)
ftp> bye
221 Goodbye!
[root@mail test]# ls
ftp.exp JavaService-2.0.10.zip script.exp test.exp test.sh
通过ls可以发现我们的ftp.exp已经成功运行,并成功将JavaService-2.0.10.zip文件下载到本地。
4、使用变量
expect命令使用set来定义变量并赋值。例如,要给变量VAR赋值5,可以如下语法:
set VAR 5
访问变量方式同shell一样,需在变量名前加字符“$”
为expect脚本定义命令行参数,可以如下语法:
set VAR [lindex $argv 0]
将上面的ftp.exp改为通用FTP交互
[root@mail test]# vi ftp.exp
#!/usr/bin/expect -f
set force_conservative 0 ;# set to 1 to force conservative mode even if
;# script wasn't run conservatively originally
if {$force_conservative} {
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s -- $arg
}
}
set rem_host [lindex $argv 0]
set rem_dir [lindex $argv 1]
set rem_file [lindex $argv 2]
set timeout -1
spawn ftp $rem_host
match_max 100000
expect "Name *: "
send -- "admin\r"
expect "Password:"
send -- "123\r"
expect "ftp> "
send -- "get $rem_file \r"
expect "ftp> "
send -- "bye\r"
expect eof</pre>
使用的时候指定相关的参数:
[root@mail test]# ./ftp.exp 192.168.0.5 / JavaService-2.0.10.zip
运行效果同上面一样。