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 |
http://blog.sina.com.cn/s/blog_6151984a0100emri.html