关闭

自动交互工具expect

252人阅读 评论(0) 收藏 举报
分类:
Expect这个工具可以自动Telnet或者Ftp到指定的服务器上,成功login之后自动执行一些命令来完成所需的工作。当然,有很多编程语言可以去解决此类问题,比如用C、Perl、或者Expect。显然,尽管C是无所不能的,但是解决此类问题还是比较困难,除非你熟悉Telnet或者Ftp协议。
曾经见过别人用C实现了一个简单的Telnet客户端协议的程序,可以在这个程序加入自己的代码来捕获服务端的输出,根据这些输出来发送适当的指令来进行远程控制。

使用Perl一样可以实现这样的功能,然而,Expect做的更出色,而且除支持Unix/Linux平台外,它还支持Windows平台,它就是为系统管理和软件测试方面的自动交互类需求而产生的:Expect是一个免费的编程工具语言,用来实现自动和交互式任务进行通信,而无需人的干预。

最好的学习方法就是边干边学,对于已经熟悉一种编程语言的人来说,用另一种新的语言来写程序解决问题,是很容易的事。所以大概了解一下基本语法后,就一边动手解决问题,一边查手册吧。

***************************************************************************************

【结合crontab定时执行任务,实现定时登陆服务器执行任务】

  1. #!/usr/bin/expect -f
  2. set timeout 30
  3. spawn ssh -l test 192.168.1.1
  4. expect "password:"
  5. send "mypassword\r"
  6. expect "~$*"
  7. send "/home/test/a.sh\r"
  8. send "exit\n"
  9. expect eof
  10. exit
***************************************************************************************

expect 的核心功能,对于设定好的特定匹配形式,以相匹配的动作以应对。每一个expect后所跟的字符串(或者正则表达式)就是脚本所等待的匹配模式,每一个send 所做的工作就是对于各种的模式串,实施相应的动作。

    第一行设定了脚本执行的程序,-f选项指的是expect执行一个文件

    第二行,设定了本脚本所有的超时时间,单位是秒(s),如果超时,脚本将继续向下进行(比如在等待某个模式出现,超时以后,会进行下一语句)。

    第三行,expect使用spawn命令来启动脚本和命令会话,这里启动的是ssh命令,这里的ssh命令将会以子进程的方式产生。

    下面就是交互的过程:ssh -l 登陆以后,会给要求客户写入密码,所以等待出现“password:”,出现password:以后,需要写入密码,注意这里需要送去回车或者换行符,否则远端主机不会收到ssh请求的。登陆上系统之后,会出现命令提示符:~$,即系统已经登陆到了远端主机的shell,然后送去要执行的命令。完毕后推出远程机器(这个send "exit\r"前也可以有上一个命令的输出,也可以没有,因为上一个命令执行完毕后会顺序执行下一条)。

    最后是等待标示子进程已结束的标示符eof,然后退出。(注:这个等待eof必须要有,如果没有eof,很可能在子进程没有结束前就退出,造成问题。)


语法说明:

Expect语言是基于Tcl的, 作为一种脚本语言,Tcl具有简单的语法:       
cmd arg arg arg:  一条Tcl命令由空格分割的单词组成. 其中, 第一个单词是命令名称, 其余的是命令参数 ;
 $foo: $符号代表变量的值. 在本例中, 变量名称是foo.;
  [cmd arg]  : 方括号执行了一个嵌套命令. 例如, 如果你想传递一个命令的结果作为另外一个命令的参数, 那么你使用这个符号;
 "some stuff" :双引号把词组标记为命令的一个参数. "$"符号和方括号在双引号内仍被解释;
 {some stuff}:大括号也把词组标记为命令的一个参数. 但是, 其他符号在大括号内不被解释;
反斜线符号是用来引用特殊符号. 例如:n 代表换行. 反斜线符号也被用来关闭"$"符号 , 引号,方括号和大括号的特殊含义 。

set myname [lindex $argv 0] 这句获取外部传入的第一个参数(argv 0)并传给变量myname,如果获取多个参数则使用argv 1,argv 2,以此类推。

    另外,expect支持一般语言所常用的if,for等流程控制语句,这个可以参看expect高级介绍

【其他】

expect "password:"] 

这里的expect也是expect的一个内部命令,有点晕吧,expectshell命令和内部命令是一样的,但不是一个功能,习惯就好了。这个命令的意思是判断上次输出结果里是否包含“password:”的字符串,如果有则立即返回,否则就等待一段时间后返回,这里等待时长就是前面设置的30秒 

send "ispass\r"] 

这里就是执行交互动作,与手工输入密码的动作等效。 

温馨提示: 命令字符串结尾别忘记加上 “\r”,如果出现异常等待的状态可以核查一下。 

interact] 

执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。如果你只是登录过去执行一段命令就退出,可改为[expect eof

$argv数组存储从脚本中传递进来的变量,数组索引从0开始。

expect -re "\[(.*)]:" //re指示为正则表达式

set prompt [lindex $argv 0] //将参数0存储到prompt变量中。

8、示例1

if {$argc<2}

{

send_user "usage: $argv0 file user1 user2 ... "

exit

}

send_user命令用来显示使用帮助信息到父进程(一般为用户的shell)的标准输出。也可以用puts

函数lindex从列表/数组得到一个特定的元素。[]用来实现将函数lindex的返回值作为set/send命令的参数。

exp_continue同C中的continue;eofend-of-file)关键字用于匹配结束符,比如文件的结束符、FTP传输停止等情况,在这个关键字后跟上动作来做进一步的控制,断开连接,退出等。





最好的学习方法就是边干边学,对于已经熟悉一种编程语言的人来说,用另一种新的语言来写程序解决问题,是很容易的事。所以大概了解一下基本语法后,就一边动手解决问题,一边查手册吧。
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:2477次
    • 积分:45
    • 等级:
    • 排名:千里之外
    • 原创:1篇
    • 转载:1篇
    • 译文:1篇
    • 评论:0条
    文章存档