Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Having problems using Expect

Status
Not open for further replies.

Sepheppi

ISP
Apr 10, 2012
2
US
I'm working on a script for my job to read a list of routers/switches from a DB, log into each one and apply a list of commands located in a separate text file.

This works great. The problem is, some devices take different commands to accomplish the same task. So I've decided to make it so there are two commands in the list, separated by a comma and I simply want it to run the second command if the first one fails. In theory, this should be pretty simple.

However, Expect seems to be a little flaky on this task. Please see the relevant code below:

if ($flag == 0) {
$fail = 0;

while (($configline = readline($config)) && !$fail ) {
#$var2 = undef;
chomp $configline; #remove garbage
next unless $configline; #go to the next line if the current onei s blank
( $configline, $var2 ) = split (/,/, $configline); #separate the commands
#print "\nConfig: $configline\n";
#print "Alt: $var2\n" if ( $var2 );
#if (!$var2){
# print $telnet "$configline"; #enter command
#}else { print $telnet "$configline\n";}
$telnet->exp_internal(1); #debug
$telnet->send("$configline\n"); #issue the command
#sleep 1;
$telnet->expect(60,
['% Invalid', #string to match if command failed
sub {
print "Made it into %!!";
$fh = shift;
$fail = 1;
$flag = 1;
if ( $var2 ){ #check if a second command exists
#print "Invalid command, trying alt: $var2\n";
$fh->send("$var2\n"); #issue second command
$var2 = undef; #reset var2 so it doesn't try again
$fail = 0; #allow for a retry
$flag = 0;
exp_continue;
}else {print "var2 was empty you moron!";}
print $errorLog localtime. " - error: $router_name# $configline \n"; #log errors
#exp_continue;
#$fh = shift;
}],
['#$',
sub {
$fh = shift;
#sleep 1;
}],
[
timeout =>
sub {
$fh = shift;
print $errorLog "oh shit fail!" . $telnet->exp_error()."\n";
$fail = 1;
$flag = 1;
}]
);

}

seek ($config, 0, 0);
}


The script runs pretty well, but it seems like expect is too ambitious. I get various outputs and I assume it's due to latency. I haven't been able to resolve it with cleverly placed 'sleep 1;' 's but the results certainly change. Please see below for an example config it's reading:

permit host 10.72.160.96,access-list 23 permit host 10.72.160.96

And below here are the outputs:

SW01.ALLN.MI(config)#permit 66.133.188.32 0.0.0.31
permit 66.133.188.32 0.0.0.31
^
% Invalid input detected at '^' marker.

SW01.ALLN.MI(config)#pMade it into %!!ermit 66.133.190.0 0.0.0.255
permit 66.133.190.0 0.0.0.255
^
% Invalid input detected at '^' marker.

SW01.ALLN.MI(config)#Made it into %!! access-list 23 permit 66.133.190.0 0.0.0.255


As you can see above, it starts running the second "first" command before applying what's in the 'if' statement, within the subroutine which sends var2.

It also even appears to break out and cause flag or fail to equal 1 since var2 is blank when it shouldn't be:

SW01.ALLN.MI(config)#permit 65.73.204.0 0.0.0.255
permit 65.73.204.0 0.0.0.255
^
% Invalid input detected at '^' marker.

SW01.ALLN.MI(config)# access-list 23 permit 65.73.204.0 0.0.0.255
SW01.ALLN.MI(config)#Trying 74.39.21.5...
Connected to 74.39.21.5.

I've also got the outputs from $telnet->exp_internal(1); below:


permit 184.16.9.0 0.0.0.255
^
% Invalid input detected at '^' marker.

SW01.ALLN.MI(config)# a
spawn id(4): Does ` input detected at \'^\' marker.\r\n\r\nSW01.ALLN.MI(config)#permit 184.16.9.0 0.0.0.255\r\npermit 184.16.9.0 0.0.0.255\r\n ^\r\n% Invalid input detected at \'^\' marker.\r\n\r\nSW01.ALLN.MI(config)# a'
match:
pattern #1: -re `% Invalid'? YES!!
Before match string: ` input detected at \'^\' marker.\r\n\r\nSW01.ALLN.MI(config)#permit 184.16.9.0 0.0.0.255\r\npermit 184.16.9.0 0.0.0.255\r\n ^\r\n'
Match string: `% Invalid'
After match string: ` input detected at \'^\' marker.\r\n\r\nSW01.ALLN.MI(config)# a'
Matchlist: ()
Calling hook CODE(0xe70460)...
Made it into %!!Sending ' access-list 23 permit host 138.83.167.128\n' to spawn id(4)
at /usr/share/perl5/Expect.pm line 1249
Expect::print('Expect=GLOB(0xeed950)', ' access-list 23 permit host 138.83.167.128\x{a}') called at updateMultiCommand.pl line 258
main::__ANON__('Expect=GLOB(0xeed950)') called at /usr/share/perl5/Expect.pm line 759
Expect::_multi_expect(60, 'ARRAY(0xead0d0)', 'ARRAY(0xeed758)') called at /usr/share/perl5/Expect.pm line 564
Expect::expect('Expect=GLOB(0xeed950)', 60, 'ARRAY(0x9ce990)', 'ARRAY(0xeed818)', 'ARRAY(0xeed500)') called at updateMultiCommand.pl line 280
Sending 'permit host 138.83.167.129\n' to spawn id(4)
at /usr/share/perl5/Expect.pm line 1249
Expect::print('Expect=GLOB(0xeed950)', 'permit host 138.83.167.129\x{a}') called at updateMultiCommand.pl line 247
Starting EXPECT pattern matching...
at /usr/share/perl5/Expect.pm line 560
Expect::expect('Expect=GLOB(0xeed950)', 60, 'ARRAY(0xf1ef80)', 'ARRAY(0xe98dd8)', 'ARRAY(0x9ce8d0)') called at updateMultiCommand.pl line 280
spawn id(4): list of patterns:
#1: -re `% Invalid'
#2: -re `#$'


Thank you for any assistance you can offer.

Joe
 
Also, here's an output when I put a sleep 1; right after the first $telnet->send("$configline\n");

SW01.ALLN.MI(config)#Made it into %!!Made it into %!!Made it into %!! access-list 23 permit host 10.74.33.48
SW01.ALLN.MI(config)#permit 10.74.12.0 0.0.0.255
permit 10.74.12.0 0.0.0.255
 
You mentioned that "The problem is, some devices take different commands to accomplish the same task"..First, I would try to send a cmd to the router that will show me the "router type" and then based on the output send the right commands to it.

e.g show version. or something like that.

Code:
$list_cmd_xxx_router=1 if ($version ~=/XXX/);

$list_cmd_yyy_router=1 if ($version ~=/YYY/);

dmazzini
GSM/UMTS System and Telecomm Consultant

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top