网上搜了很多关于expect交互的说明,但都不详,只简单注明用法..

现整理归档下:

1.expect简述:

  Expect 作为基于 Tcl 的高级语言,增加了一些特殊的语法,此外,Expect 已经以模块的方式移植到了 Perl 和 Python 语言中,因此用户同样可以在 Perl 和 Python 脚本中利用 Expect 强大的交互功能。
 

Send,expect 和 spwan 是 Expect 语言最基本的命令。其中,send 命令会发送字符串给指定进程(process);

expect 命令会等待接受该进程返回的结果并且会根据返回的字符串来决定下一步的操作;

而 spwan 命令可以发起一个进程的运行。

send命令接收一个字符串作为参数发送给指定进程。如 send "hello world\n" send 会送出字符串“Hello world”( 不带引号 )。如果 Expect 早已经开始与某一个程序进行交互,那么这个字符串将被发送给该程序;一般是发送到标准输出的, expect 命令则等待一个响应,通常是来自于 Expect 正在与之交互的进程,或者来自于标准输入设备;它会等待一个指定的字符串或者满足给定的正则表达式的任何字符串。

2.expect命令执行选项:

1) -c  从命令行执行expect脚本

#expect -c  'expect "\n"' {send "pressed enter\n"}  执行等待输入换行符\n按回车后会打印出presssed enter

2) -i  选项交互执行脚本

#expect -i arg1 arg2 arg3

expect1.1>set argv

arg1 arg2 arg3

expect1.2>

正常情况不加-i执行,会把arg1当作为脚本文件名,-i选项可以让脚本把多个参数当一个连续的列表.

3) -d 调试脚本信息

#expect -d 脚本名

4) 读入命令行参数

cat print_cmdline_args.exp

  1. #!/usr/bin/expect  
  2. puts 'agrv0 : [ lindex $argv 0]';puts 'argv1 : [lindex $argv1]';  
  3. 读入第一个和第二个参数 

 #expect  print_cmdline_args.exp aa bb    执行此脚本传递aa,bb参数

3.expect 语法

 1) expect partlist1 action1 partlist2 action2

  1. #!/usr/bin/expect  
  2. pwd=12345 
  3. timeout=300s    默认10s  
  4. expect {  
  5.       -re "password:" {send "$pwd\n"}  
  6.       -re "yes\no:" {send "yes\n"}  
  7. }  
  8. expect一直等到当前进程的输出和以上的某一个模式相匹配(如:返回要求输入的密码)或等到timeout超时,或等到遇到了文件的结束为止。  

每一个partlist都由一个模式一列表组成,如果有一个模式匹配成功,相应的action就会执行,执行结果从expect返回。

2)被精确匹配的字符串(或当超时发生时,已经读取来进行匹配的字符串)被存贮在变量expect_match里。如果partlist是eof或timeout则文件发生结束或超时时才执行相应的action.

  1. expect "*welcome*" break  
  2.        "*busy*" {print busy;continue}  支持分号分隔多个语句  
  3.        "*failed*"  abort  
  4.        timeout   abort  
  5. 注:abort在脚本的别处有定义:  
  6.     exec sleep 4  使程序暂停4s  
  7.     spawn .... 

3)修改密码样例:

  1. spawn passwd [index $argv 1]   以用户名作为参数启动程序  
  2. set passwd [index $argv 2]     设置密码变量  
  3. expect "*passwd:"           返回匹配到含有passwd字符,没有后继的action,则继续执行下面的语句  
  4. send "$passwd"              把密码发送给当前进程  
  5. expect "*passwd:"  
  6. send "$passwd"       
  7. 两次密码确认。  
  8. expect eof    作用是在password 的输出中搜索文件结束符.必须  

4)更加完善的匹配考虑:

  1. spawn passwd [ index $argv 1 ]  
  2.  
  3. expect eof {exit 1}  
  4. timeout    {exit 2}  
  5.         "*No such user.*"  {exit 3}  
  6.         "*New password:"  
  7.         send "[index $argv 2]"  
  8.  
  9. expect eof {exit 4}  
  10. timeout {exit 2}  
  11.         "*Retype new password:"  
  12.         send "[index $argv 3]"  
  13.  
  14. expect timeout {exit 2}  
  15.        "*Missmatch*" {exit 6}  
  16.        "*Password unchanged*" {exit 7}  
  17.  
  18. 此脚本退出时用数字表示所发生的情况。  
  19. 如0表示password正常运行,1表示非预期死亡,2表示锁定.....  
  20. expect返回字符串和数学是一样的。 

5)伪终端:提供了终端语义以便程序认为他们正在和真正的终端进行I/O操作。

  1. for {} {} {  
  2.          spawn ...  
  3.          expect "...." break  
  4.          ...    "...."  
  5.          close   关闭和伪终端的连接  
  6.      wait   等待退出  
  7. }  
  8. interact   进入交互终端不退出 

6)ftp取文件样例:

  1. spawn ftp [index $argv 1]   第一个参数主机名  
  2. expect "*Name"  
  3. send "anoymous"  
  4. expect "*Password:*"  
  5. send [exec whoami]  
  6. expect "*ok*ftp>*"  
  7. send "get [index $argv 2]"  下载所需的文件  
  8. expect "*ftp>*" 

7) 提到的内个命令:

expect_user   从标准输入中读取

send_user  命令发送字符串到标准输出,只是当执行expect开始时send的方式。(发送命令给当前用户)例:

  1. send_user "logging in as anoymous\n"  
  2. send "anoymous\r"  
  3.  
  4. 发送操作说明型字符串 

log_user 0  关闭标准输出

待续...

 

参考说明:

http://bbs.linuxtone.org/forum.php?mod=viewthread&tid=7185