Chinaunix

标题: 关于perl telnet的prompt问题 [打印本页]

作者: zljjg2000    时间: 2016-07-31 15:04
标题: 关于perl telnet的prompt问题
本帖最后由 zljjg2000 于 2016-07-31 15:04 编辑

程序如下:
open(FILE,"<E:/设备中心/1-包机/2015-专线提取/$ARGV[0]")||die"cannot open the file: $!\n";
#程序执行时,手工输入sr.pl source-ne40e.txt;
#source-ne40e里存放着所有ne40e的ip地址清单;

use Net::Telnet();
#引入Net::Telnet模块
$username="xxx";
$passwd="xxx";
while (<FILE>)
{
   $line1=$_;
   @list1=split(/\s+/,$line1);
   $host=$list1[0];
   $tishifu=$list1[1];
   
#$host取出ne40e的ip地址
   unlink  "dest-ne40e.txt";
#删除程序运行前已经存在的老的dest-ne40e.txt;


$t = new Net::Telnet (Timeout => 10,Prompt => $tishifu);
$t->open($host);
$t->login($username, $passwd);
sleep(3);
$t->cmd("sys");
sleep(3);
$t->cmd("user-interface vty 0 4");
sleep(3);
$t->cmd("screen-length 0");
sleep(3);
@lines = $t->cmd("dis version");
print @lines;

}
close FILE;
close EP;
close FP;
#关闭文件句柄

注:source-ne40e.txt文件里存放内容如下:
192.168.1.1 <NE40E-X16-S1>
192.168.1.2 <NE40E-X8-S1>

运行程序sr.pl source-ne40e.txt, 结果报错如下:

bad Prompt argument "<NE40E-X16-S1>": missing opening delimiter of matc
h operator at E:\设备中心\1-包机\2015-专线提取\sr.pl line 23

将$tisihfu直接写成'<NE40E-X16-S1>',也不行,求教高手。
作者: laputa73    时间: 2016-07-31 20:54
本帖最后由 laputa73 于 2016-07-31 20:55 编辑

不能用cmd
要用print和waitfor
cmd的prompt是写死的
作者: 大米白面    时间: 2016-08-01 10:38
需要对 '/' 转义。

"\/"
作者: zljjg2000    时间: 2016-08-02 17:11
本帖最后由 zljjg2000 于 2016-08-02 17:13 编辑

谢谢楼上们的解答,现在程序修改后,报错变成了下面的信息:
程序修改后:
open(FILE,"<E:/设备中心/1-包机/2015-专线提取/$ARGV[0]")||die"cannot open the file: $!\n";
#程序执行时,手工输入sr.pl source-ne40e.txt;
#source-ne40e里存放着所有ne40e的ip地址清单;

open(EP,">>E:/设备中心/1-包机/2015-专线提取/result");
#将执行结果存放到result文件中

use Net::Telnet();
#引入Net::Telnet模块
$username="xxx";
$passwd="xxx";
while (<FILE>)
{
    $line1=$_;
    @list1=split(/\s+/,$line1);
    $host=$list1[0];
    $tishifu="/".$list1[1]."/";   ------------已将$tishifu修改了
   
#$host取出ne40e的ip地址
   unlink  "dest-ne40e.txt";
#删除程序运行前已经存在的老的dest-ne40e.txt;


my $t = new Net::Telnet ('Host'=>$host,Timeout => 10,Prompt => $tishifu,Output_Log=>"E:/设备中心/1-包机/2015-专线提取/Output_log.log");
$t->waitfor('Match'=>"/Username:/");
$t->print($username);
$t->waitfor('Match'=>"/ord:/");
$t->print($passwd);
$t->waitfor('Match'=>"/\>/");
$t->print("sys");
sleep(3);
$t->print("user-interface vty 0 4");
sleep(3);
$t->print("screen-length 0");
sleep(3);
my @lines=$t->cmd(String=>"disp arp interface Eth-Trunk 3.410");      --------第50行
print EP @lines;
print @lines;
$t->print("exit");
$t->print("screen-length 24");
$t->print("exit");
$t->close(); }
close FILE;
close EP;
close FP;
#关闭文件句柄

注:source-ne40e.txt文件里存放内容如下:
192.168.1.1 <NE40E-X16-S1>
192.168.1.2 <NE40E-X8-S1>

运行程序sr.pl source-ne40e.txt, 结果报错如下:

command timed-out at E:\设备中心\1-包机\2015-专线提取\sr.pl line 50

这是怎么回事啊?
若要将cmd换成print,那程序能通过,但是就无法将disp arp interface Eth-Trunk 3.410的命令结果保存下来了。

注:source-ne40e.txt文件里存放内容如下:
192.168.1.1 <NE40E-X16-S1>
192.168.1.2 <NE40E-X8-S1>

作者: laputa73    时间: 2016-08-02 17:35
本帖最后由 laputa73 于 2016-08-02 17:48 编辑

善用waitfor的返回
($prematch, $match)=$sess->waitfor(Match => $str, Timeout => $to);

忘掉cmd和login吧,那是给主机专用的。
作者: laputa73    时间: 2016-08-03 08:45
简单来说,每一次print,都必需跟至少一个waitfor(其实就是expect),来保证输出缓冲区被读取
如果用数组来取,就是被存到prematch部分
如果用标量来取,就被丢弃了
如果你不取,那么缓冲区内容保留,和下一次的print内容叠加
再次waitfor时,实际取到的是前一次print的结果

你的print passwd后面没有waitfor,造成了错位。
print+sleep那是tcl的笨做法。

你可以看到因为你设的str是NE40E-X16-S1,所以打印的信息没有包含后面的]
这个就是prompt的选取问题,要保证match到的最好是最后一个字符,否则缓冲区就可能没被取完
注意。普通模式的结尾字符是>,sys模式的结尾字符是]


作者: zljjg2000    时间: 2016-08-03 17:46
谢谢laputa73大侠,我明白了。
感觉print和waitfor还挺脆弱的。。。
不过net::telnet对于网络维护人员,这方面的工具还挺好的




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2