免费注册 查看新帖 |

Chinaunix

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

Perl expect [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-05-09 15:59 |只看该作者 |倒序浏览

转载本站文章请注明,转载自:扶凯[http://www.php-oa.com]

本文链接: http://www.php-oa.com/2009/09/16/perl-expect.html

Perl实在大方便了,如果用它来玩expect,是相当的好,不用在学一次expect的语法.只要了解perl就行了. 下面是我看官方的文章还有自己使用中总结的一些经验.呵呵,我有新的心得就会来更新的….

perl的expect基本使用方法.
  1. $exp = new Expect;  #new一个Expect.
  2. $exp->spawn($command,@params);  #fork和exec一个新进程用来执行$command命令.
  3. $exp->expect($timeout,$content); #'-re'.在$timeout内,期待出现包含$content内容的正则表达式,如果不加re默认是精确匹配,也可以使用正则表达式,expect($timeout,re=>'').
  4. $exp->send($string);  #向终端发送字符
  5. $exp->debug(0|1|2);  #打印debug 信息,不同的数字表示不同的bug级别
  6. $exp->interact();   #和用户进行交互,把控制权转交给用户
  7. $exp->soft_close();  #软关闭,直到$timeout时间到达,才关掉该进程
  8. $exp->hard_close();  #硬关闭,立刻关闭该进程
  9. $exp->match();   #返回匹配的结果
  10. $exp->match_number(); #返回匹配的个数
  11. $exp->send_slow(); # 就是让command慢慢敲进去..
  12. $exp->stty(); #它和外部命令 stty 类似,设定 terminal 的模式,-raw 还是 -cooked。开关回显 echo 和 -echo。
复制代码


exp_continue 一般在 expect 命令中使用,它可以避免写第二次 expect 命令,即如果匹配上某个模式,然后需要做一些事情(如输入密码什么的),之后需要继续匹配,因此需要第二次 expect 命令。exp_continue 可以重复本次 expect 命令,因此也就不需要再次写一个 expect 命令,而可以将两个写在一起。

常用技巧和功能

我们想让程序只在后台跑就行了,不会跑到前面来影响我们.所以我们需要expect的关掉终端显示的功能.

$Expect::Log_Stdout = 0;$exp->log_stdout(0);

注:0为关掉显示,1为打开

希望expect一直等到某个字符出现需要怎么样做

$exp->expect(undef,sub {})

如果不希望expect等,就使用$exp->expect(0),这样当前如果有这个字符就成功,没有就跳过.

取得expect的命令行中有输出,使用before来取得数据来进行处理

my $read = $exp->before();print $read;

注意,这个得到的内容,是从expect中匹配到的内容.

在使用expect时,日志中有很多特别的符号,使用下面这个terminal type的设定,就会好了. 不知为什么,日志文件中会有很多^[ ,^G之类的字符,如果用了下面的参数就行了,只有一个^M,这个用dos2unix就行了

$ENV{TERM} = "xterm";

打开内部调试,这样可以让后续命令的诊断信息发送到 Expect 所控制的 stderr,这样可以显示出比如$exp->expect()中的内容是否匹配.这样可以显示看到显示的字符,方便调试匹配规则,

$exp->exp_internal(1);

注意:internal这个必须写到spawn后面 打开debug模块,可以显示连接的过程,进程的退出之类的状态

$exp->debug(3);

记录expect的日志到一个文件

$exp->log_stdout(1);$exp->log_file("output.log"); #注意,这句一定要写在Expect->spawn之后,不然expect会没有日志输出中间发送和匹配之类的过程.......$exp->log_file(undef);

在expect时,追加日志到一个文件

$exp->log_file("filename");

默认是追加,如果要修改就用

$exp->log_file("filename", "w");

在perl的expect中怎么发送控制字符,
比如
ctrl+c control-G $exp->send(“\cG”);
control-c $exp->send(“\cC”;);

我设置了一个终端大小,但是修改窗口大小后,我的Expect不能发现窗口改变. 主要是远程不能抓到本地的WINCH”window size changed”的信号,当我修改我本地终端大小时需要传送信息给spawn.

  my $exp = new Expect;  $exp->slave->clone_winsize_from(\*STDIN);  $exp->spawn("ssh somehost);  $SIG{WINCH} = \&winch;   sub winch {    $exp->slave->clone_winsize_from(\*STDIN);    kill WINCH => $exp->pid if $exp->pid;    $SIG{WINCH} = \&winch;  }   $exp->interact();

一个简单的Perl使用Expect自动登陆服务器的实例
  1. #!/usr/bin/perl
  2. use Expect;
  3. $Expect::Log_Stdout = 1;

  4. $ENV{TERM} = "vt100";

  5. my ($host,$pass) = ("host","passwd");
  6. my $exp = Expect->new;
  7. $exp = Expect->spawn("ssh -l root $host");
  8. $exp->log_file("output.log", "w");
  9. $exp->expect(2,[
  10.                     qr/password:/i,
  11.                     sub {
  12.                             my $self = shift ;
  13.                             $self->send("$pass\n");
  14.                             exp_continue;

  15.                         }
  16.                 ],
  17.                 [
  18.                     'connecting (yes/no)',
  19.                     sub {
  20.                             my $self = shift ;
  21.                             $self->send("yes\n");
  22.                          }
  23.                 ]
  24.             );
  25. #$exp->interact() if ($exp->expect(undef,'#'));
  26. $exp->send("uptime\n") if ($exp->expect(undef,'#'));
  27. $exp->send("exit\n") if ($exp->expect(undef,'#'));
  28. $exp->log_file(undef);
复制代码



您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP