作文最后一个人续写:EXPECT

来源:百度文库 编辑:偶看新闻 时间:2024/05/10 10:58:41

EXPECT

(2009-08-11 14:54:40) 转载标签:

expect

语法

编程注意事项

分类: perl,cgi,shell脚本编程
expect 概念
Expect除支持Unix/Linux平台外,它还支持Windows平台
用过secureCRT的人应该知道有个自动登录的设置,那就是利用expect实现的


expect 安装需要那些包支持----tcl包和tk包
linux上
[root@str0121bk RPMS]# rpm -ivh expect-5.38.0-74.i386.rpm
warning: expect-5.38.0-74.i386.rpm: V3 DSA signature: NOKEY, key ID db42a60e
error: Failed dependencies:
libtcl.so.0 is needed by expect-5.38.0-74
libtk.so.0 is needed by expect-5.38.0-74
solaris上
expect-5.43.0-sol10-x86-local.gz Expect is a program that performs programmed dialogue with other interactive programs
- installs in /usr/local. You should also get tcl-8.5a4 , tk-8.5a4 and, if you don't have gcc installed, libgcc.


expect几大基本命令
spawn telnet 192.168.1.12 激活一个Unix程序 
expect “ 等待进程的某些字符串
send “ 向进程发送字符串
send_user “ send_user相当于echo和printf
set timeout 5 expect 类似C SHELL,赋值用set语句,不用=


expect 命令特点
expect类似switch/case,能同时等待多个字符串,并对每一个字符串执行不同的操作
expect还能理解一些特殊情况,如超时和遇到文件尾
expect timeout
expect eof


expect { }——用于多个pattern,相当于case语句
expect {
pattern
{
action
}
pattern
{
action
}
pattern
{
action
}
}


expect 的括号要么不加,一加就是两层
expect "*$*"
send "exit\n"expect {
"*$*"
{
send "exit\n"
}
}


expect括号的作用
spawn ftp 10.1.1.1
...
expect timeout
exit

由于expect脚本是顺序执行的,那么当程序执行到这个expect timeout的时候就会阻塞,程序会一直等待到timeout然后退出
expect {
timeout exit
Connect
}
换成括号,timeout只要被辨认,就会执行后面的exit

其实不必特别处理expect { timeout exit 0 },expect 的set timeout 3就能解决异常中断/等待的问题
比如FTP SERVER连接不上时,仍执行自动FTP 脚本
set timeout 3 超过timeout,就跳过expect语句
执行expect下面的send语句$ ./expecttest
spawn ftp 192.168.1.11
ftp: connect: Connection refused
ftp> macg
Invalid command
ftp> 008421

bin
Invalid command
ftp> ftp> Not connected.
ftp> get asian_0264_4.mpg
Not connected.
ftp> quit
success


expect函数
定义在前
proc name {参数1 参数2} {
command
command
}
引用在后
name 参数1值 参数2值


expect文档内命令行参数的引用: [ index $argv num ]
spawn ftp [index $argv 1]
expect "*Name*"
send "anonymous "
expect "*Password:*"
send [exec whoami]
expect "*ok*ftp>*"
send "get [index $argv 2] "
expect "*ftp>*"


usage: send [args] string


interact指令 ----在expect 里面引如interact交互动作,使expect更灵活,可以自动也可以手动
for {} {1} {} {
expect
eofbreak
"*UNREF FILE*CLEAR?"{send "r "}
"*BAD INODE*FIX?"{send "y "}
"*?"{send "n "}
}
for {} {1} {}{
expect
eofbreak
"*UNREF FILE*CLEAR?"{send "y "}
"*BAD INODE*FIX?"{send "y "}
"*?"{interact +}
}在这个版本里面,如果脚本遇到了”?”执行interact命令把控制交给用户
此时用户的手工输入击键交给fsck处理。
当执行完后,用户可以通过按"+"键来退出或者把控制交还给expect



=================================expect编程注意事项=======================================

expect 必须带#!/usr/bin/expect,否则运行出错

send 如何输入回车符号?
正规的回车是\n ,注意是反杠,参数杠,不是目录杠
$ vi expecttest
#!/usr/bin/expect
set timeout 3
spawn telnet 192.168.1.12
expect "*login:*"
exec sleep 1
send "test\n" 回车
expect "*Password:*"
exec sleep 1
send "008421\n" 回车
expect "*test*"
exec sleep 1
也可以用直接用回车,缺陷是带换行,使send语句分到两行中
#!/usr/bin/expect
set timeout 3
spawn telnet 192.168.1.12
expect "*login:*"
exec sleep 1
send "test
"
expect "*Password:"
exec sleep 1
send "008421
"


expect " "内不能包含特殊符号
expect "*[test*" 想匹配[test@localhost ~]$系统报错
missing close-bracket
while executing
"expect "*[test*"


expect 后不必只跟一个send指令,可以跟多个send 指令
expect "*$*"
send "uname -p\n"
expect "*$*"
send "pwd\n"
send "ls -l\n"
[test@localhost ~]$ uname -p
i686
[test@localhost ~]$ pwd
/home/test
[test@localhost ~]$ ls -l
total 4


expect 输入 sleep 是经常的,因为自动执行受制于系统响应时间和send内指令的执行时间
expect 没有抑制后边send指令的机能
所以只能人为加 sleep 指令
expect "ftp>"
send "bin\n"
exec sleep 1
send "get asian_0264_4.mpg\n"
exec sleep 1
expect "ftp>"
send "quit\n"
ftp> get asian_0264_4.mpg
local: asian_0264_4.mpg remote: asian_0264_4.mpg
227 Entering Passive Mode (192,168,1,11,4,10).
150 Opening data connection for asian_0264_4.mpg.
quit
226 Transfer complete.
Sleep 1太短了,还没传完,就quit了expect "ftp>"
send "bin\n"
exec sleep 1
send "get asian_0264_4.mpg\n"
exec sleep 4
expect "ftp>"
send "quit\n"
ftp> bin
200 Type set to I.
ftp> get asian_0264_4.mpg
local: asian_0264_4.mpg remote: asian_0264_4.mpg
227 Entering Passive Mode (192,168,1,11,4,11).
150 Opening data connection for asian_0264_4.mpg.
226 Transfer complete.
1269764 bytes received in 1.4 seconds (8.6e+02 Kbytes/s)
ftp> quit
221 Goodbye!


上面例子的另一个解决办法:选择合理的expect pattern, 可以避免执行sleep指令
#!/usr/bin/expect
set timeout 3

spawn ftp 192.168.1.11
expect "*Name*"
exec sleep 1
send "macg\n"
expect "*Password:*"
exec sleep 1
send "008421\n"
send "\n"
expect "ftp>"
send "bin\n"
expect "*set to I*"
send "get asian_0264_4.mpg\n"
expect "*complete*"
expect 合理的上一条指令的输出,好send下一条指令
send "quit\n"
expect "*$*"
send_user "success\n"
$ ./expecttest
spawn ftp 192.168.1.11
Connected to 192.168.1.11.
221 Goodbye!
500 'AUTH': command not understood.
500 'AUTH': command not understood.
KERBEROS_V4 rejected as an authentication type
Name (192.168.1.11:macg): macg
331 Password required for macg.
Password:
230 User macg logged in.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ftp> bin
200 Type set to I.
ftp> get asian_0264_4.mpg
local: asian_0264_4.mpg remote: asian_0264_4.mpg
227 Entering Passive Mode (192,168,1,11,4,70).
150 Opening data connection for asian_0264_4.mpg.
226 Transfer complete.
1269764 bytes received in 1.5 seconds (8.4e+02 Kbytes/s)
ftp> quit
221 Goodbye!
success



expect 文件缺陷,最后一个expect语句后面的所有send语句都不执行 所以为了让所有的send语句都执行,必须用一个不带send 的expect语句结尾
(但最后一个expect语句后面的send_user语句会被执行)
$ vi expecttest
#!/usr/bin/expect
set timeout 3

spawn telnet 192.168.1.12
expect "*login:*"
exec sleep 1
send "test\n"
expect "*Password:*"
exec sleep 1
send "008421\n"
send "\n"
expect "*$*" 此句成了最后一个expect语句
send "pwd\n"
send "ls -l\n"

send_user "success\n"

$ ./expecttest
spawn telnet 192.168.1.12
Trying 192.168.1.12...
Fedora Core release 4 (Stentz)
Kernel 2.6.11-1.1369_FC4 on an i686
login: test
Password:
发觉send pwd和ls –l语句都没有执行
[test@localhost ~]$ success 但send_use指令被执行$ vi expecttest
#!/usr/bin/expect
set timeout 3

spawn telnet 192.168.1.12
expect "*login:*"
exec sleep 1
send "test\n"
expect "*Password:*"
exec sleep 1
send "008421\n"
send "\n"
expect "*$*"
send "pwd\n"
send "ls -l\n"

expect "*$*" 结尾填加一个没什么用处的expect "*$*"



$ ./expecttest
spawn telnet 192.168.1.12
Trying 192.168.1.12...
login: test
Password:
[test@localhost ~]$
[test@localhost ~]$ pwd
/home/test
[test@localhost ~]$ ls -l
total 4 结尾填加的expect,使最后两句send指令可以执行
-rw-rw-r-- 1 test test 0 Jan 2 21:26 11