免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1514 | 回复: 0
打印 上一主题 下一主题

expect vs shell [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-08-15 22:13 |只看该作者 |倒序浏览
  最近调试程序,由于测试数据集过大,程序要跑几天几夜, 还好,测试集有一定的独立性,这就使我有空子钻了---把程序分到多台机子上运行,再把数据重定向到本机上,嘿嘿。
  这样搞过一次,用了8台机子,运行了10个多小时,还是偷偷的ssh到别人的机子上运行的---不要说我rp不好,反正晚上嘛,我偷偷的用一下也没什么影响:)
  不过,其实发现这样其实还是很麻烦的, 要分别ssh 上去,还要手工计算分配数据段,重定向。。。etc。。总之用的机子越多越麻烦,还容易出错。。
  于是乎,自然想到写段 shell script 解决,不过很遗憾的发现,shell的话 ssh上去就停在那里的,其实也不奇怪,shell 为了安全起见,对程序提供了最小限度的控制(想启动的程序发送消息等),而把所有的交互都留给了用户, 也就是说shell基本不能运行交互式的程序了---比如那些执行期间要你输入选择的程序。。
我这样的需求,那用shell跟不用差不多了----到交互的时候都是要自己手动敲命令的。。
   当然不甘心了, google之,发现有个专门干这个事的东西: expect  ---以前从来没听过这个 :)
“Expect是一个免费的编程工具语言,用来实现自动和交互式任务进行通信,而无需人的干预”, 粗略看了下语法,感觉我的问题可以很轻易的解决,试了一下,果不其然^_^, expect真是个好东西。。
贴下我的expect script :
      1 #! /usr/bin/expect
      2 proc process { name disk step } {
      3 spawn ssh $name
      4 expect "*:)*"
      5 puts "ssh $name ok"
      6 send " cd **some dir** \n "
      7 expect "*:)*"
      8 puts "cd ok"
      9 append file "data_" $disk "_" $step
     10 puts $file
     11 append param1 "--disk=" $disk
     12 append param2 "--step=" $step
     13 send " ./moon $param1 $param2  > $file & \n"
     14 expect "*:)*"
     15 puts " run moon ok"
     16 send " exit \n"
     17 expect "*:)*"
     18 puts "exit ok"
     19 }
     20
     21 set step [ expr 140000/$argc +1 ]
     22 set disk 0
     23 for { set i 0 } { $i  Expect是一个免费的编程工具语言,用来实现自动和交互式任务进行通信,而无需人的干预。
  Expect的作者Don Libes在1990年开始编写Expect时对Expect做有如下定义:
        
  Expect是一个用来实现自动交互功能的软件套件(Expect [is a] software suite for automating interactive tools)。
引用:  Expect语言是基于Tcl的, 作为一种脚本语言,Tcl具有简单的语法:      

                cmd arg arg arg  
                一条Tcl命令由空格分割的单词组成. 其中, 第一个单词是命令名称, 其余的是命令参数 .  
                $foo  
                $符号代表变量的值. 在本例中, 变量名称是foo.  
                [cmd arg]  
                方括号执行了一个嵌套命令. 例如, 如果你想传递一个命令的结果作为另外一个命令的参数, 那么你使用这个符号 .
                "some stuff"  
                双引号把词组标记为命令的一个参数. "$"符号和方括号在双引号内仍被解释 .  
                {some stuff}  
                大括号也把词组标记为命令的一个参数. 但是, 其他符号在大括号内不被解释.  
               
                反斜线符号() 是用来引用特殊符号. 例如:n 代表换行. 反斜线符号也被用来关闭"$"符号 , 引号,方括号和大括号的特殊含义 .
   
  最好的学习方法就是边干边学,对于已经熟悉一种编程语言的人来说,用另一种新的语言来写程序解决问题,是很容易的事。所以大概了解一下基本语法后,就一边动手解决问题,一边查手册吧。
  关于Tcl和Expect的语法,请参考Unix/Linux 平台任务的自动化相关部分。

引用:  例1:下面是一个telnet到指定的远程机器上自动执行命令的Expect脚本,该脚本运行时的输出如下:
# /usr/bin/expect sample_login.exp root 111111
spawn telnet 10.13.32.30 7001
Trying 10.13.32.30...
Connected to 10.13.32.30.
Escape character is '^]'.
accho console login: root
Password:
Last login: Sat Nov 13 17:01:37 on console
Sun Microsystems Inc.   SunOS 5.9  May 2004
#
Login Successfully...
# uname -p
sparc
# ifconfig -a
lo0: flags=2001000849 mtu 8232 index 1
        inet 127.0.0.1 netmask ff000000
eri0: flags=1000843 mtu 1500 index 2
        inet 10.13.22.23 netmask ffffff00 broadcast 10.13.22.255
        ether 0:3:ba:4e:4a:aa
# exit
accho console login:
Finished...

引用:  下面是该脚本的源代码:
# vi sample_login.exp:
proc do_console_login {login pass} {
        set timeout 5
        set done 1
        set timeout_case 0
        while ($done) {
                expect {
                        "console login:" { send "$loginn" }
                        "Password:" { send "$passn" }
                        "#" {
                                set done 0
                                send_user "nnLogin Successfully...nn"
                        }
                        timeout {
                                switch -- $timeout_case {
                                        0 { send "n" }
                                        1 {
                                                send_user "Send a return...n"
                                                send "n"
                                        }
                                        2 {
                                                puts stderr "Login time out...n"
                                                exit 1
                                        }
                                }
                                incr timeout_case
                        }
                }
        }
}
proc do_exec_cmd {} {
        set timeout 5
        send "n"
        expect "#"
        send "uname -pn"
        expect "#"
        send "ifconfig -an"
        expect "#"
        send "exitn"
        expect "login:"
        send_user "nnFinished...nn"
}
if {$argc"
send "o 202.199.248.11r"
expect {
"Connected" break
"refused" { sleep 10} ;
}
}
这里使用了我们在tcl语言中讲到的while和break命令,熟悉C的读者应该很容易看出
它的行为:不断地等待ftp>提示符,在提示符下面发送连接远端服务器的命令,如果服
务器回应是refused(连接失败),就等待10秒钟,然后开始下一次循环;如果是Conne
cted,那么就跳出循环执行下面的命令。sleep是expect的一个标准命令,表示暂停若干
秒钟。
expect还支持许多更复杂的进程控制方式,如fork,disconnect等等,你可以从手册
页面中得到详细的信息。另外,各种tcl运算符和流程控制命令,包括tcl函数也可以使
用。
有些读者可能会问,如果expect执行的话是否控制台输入不能使用了,答案是否定的
。expect命令运行时,如果某个等待的信息没有得到,那么程序会阻塞在相应的expect
语句处,这时,你在键盘上输入的东西仍然可以正常地传递到程序中去,其实对于那些
expect处理的信息,原则上你输入的内容仍然有效,只是expect的反映太快,总是抢在
你的前面“输入”就是了。知道了这一点之后,你就可能写一个expect脚本,让expect
自动处理来自fscki的那些恶心的yes/no选项(我们介绍过,这些yes/no其实完全是多余
的,正常情况下你除了选择yes之外什么也干不了)。
缺省下,expect在标准输出(你的终端上)输出所有来自应用程序的回应信息,你可
以用下面的两个命令重定向这些信息:
log_file [文件名]
这个命令让expect在你设置的文件中记录输出信息。必须注意,这个选项并不影响控
制台输出信息,不过如果你通过crond设置expect脚本在半夜运行的话,你就确实可能需
要这个命令来记录各种信息了。例如:
log_file expect.log
log_user 0/1
这个选项设置是否显示输出信息,设置为1时是缺省值,为0 的话,expect将不产生任
何输出信息,或者说简单地过滤掉控制台输出。必须记住,如果你用log_user 0关闭了
控制台输出,那么你同时也就关闭了对记录文件的输出。
这一点很让人困扰,如果你确实想要记录expect的输出却不想让它在控制台上制造垃
圾的话,你可以简单地把expect的输出重定向到/dev/null:
./test.exp > /dev/null
你可以象下面这样使用一对fork和disconnect命令。expect的disconnect命令将使得
相应的进程到后台执行,输入和输出被重定向到/dev/null:
if [fork]!=0 exit
disconnect
fork命令会产生出一个子进程,而且它产生返回值,如果返回的是0,说明这是一个子
进程,如果不为0,那么是父进程。因此,执行了fork命令之后,父进程死亡而子进程被
disconnect命令放到后台执行。注意disconnect命令只能对子进程使用。
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/23273/showart_360756.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP