twofish has asked for the wisdom of the Perl Monks concerning the following question:

Hi all,
I have a script that logs into some cisco routers (input from a file), and then executes some commands (input from a file). Then logs all the command output.
My issue is that if a node is unreachable for any reason, I want to the script to skip it and continue on its merry way with the rest of the devices. This is probably somewhat easy, but I have experimented with warn and die, eval etc.. but haven't got it working. Below is the code:
1 #!/usr/local/bin/perl 2 3 use Net::Telnet (); 4 5 open(ROUTER_LIST, "routers.txt") || die "can't open the file c +ontaining the list of routers"; 6 @routers = <ROUTER_LIST>; 7 close(ROUTER_LIST) || die "couldn't close the file containing +the list of routers"; 8 9 open(COMMAND_LIST, "commands.txt") || die "can't open the file + containing the list of commands"; 10 @commands = <COMMAND_LIST>; 11 close(COMMAND_LIST) || die "couldn't close the file containing + the list of commands"; 12 13 ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localt +ime(time); 14 $tstamp = sprintf("%d%02d%02d%02d%02d", $year+=1900, ++$mon, $ +mday, 15 $hour, $min); 16 17 my $USER = "user1"; 18 chomp $USER; 19 20 print "enter user1 password: "; 21 my $PASS = <STDIN>; 22 chomp $PASS; 23 24 print "enter device enable passwd: "; 25 my $ENABLE = <STDIN>; 26 chomp $ENABLE; 27 28 29 30 foreach $router (@routers) 31 { 32 chomp ($router); 33 34 my $dir = "/home/net/user1/scripts/STALE_ROUTES/ROUTERS/"; 35 chdir( $dir ) or die "Cant chdir to $dir $!"; 36 37 my $ld = `ls`; 38 unless ($ld =~ /$router/i) { 39 mkdir("$router",0755) || die "cannot mkdir $router: $!"; 40 } 41 42 my $telnet = new Net::Telnet(Prompt => "/${router}#\\s*\$/"); 43 44 # $telnet->dump_log('dump_log.log'); 45 # $telnet->input_log('-'); 46 # $telnet->output_log('output_log.log'); 47 48 $telnet->open($router); 49 $telnet->waitfor('/Username: $/i'); 50 $telnet->print($USER); 51 $telnet->waitfor('/Password: $/i'); 52 $telnet->print($PASS); 53 print "=" x 72; 54 print "\n"; 55 print "Logged into ", $router, "\n\n"; 56 57 $telnet->waitfor("m/$router\>/"); 58 $telnet->print("enable"); 59 $telnet->waitfor('/Password: $/i'); 60 $telnet->print("$ENABLE"); 61 $telnet->waitfor("m/$router\#/"); 62 63 foreach $command (@commands) 64 { 65 chomp ($command); 66 67 my $dir = "/home/net/user1/scripts/STALE_ROUTES/ROUTER +S/$router"; 68 chdir( $dir ) or die "Cant chdir to $dir $!"; 69 70 my @output = $telnet->cmd("$command"); 71 print @output; 72 open(OUT, ">$router-$command-$tstamp"); 73 print OUT @output; 74 close(OUT); 75 76 77 $telnet->buffer_empty; 78 $telnet->max_buffer_length(10*1024*1024); 79 $telnet->timeout(20); 80 } 81 82 $telnet->close; 83 }

Replies are listed 'Best First'.
Re: Skipping unreachable nodes in script.
by jettero (Monsignor) on Jan 11, 2007 at 21:52 UTC

    I must recommend Net::Telnet::Cisco. It will save you a lot of trouble in the long run.

    Happily, it returns a result you could use for skipping purposes:

    $ok = $obj->login($username, $password);

    -Paul

Re: Skipping unreachable nodes in script.
by johngg (Canon) on Jan 11, 2007 at 23:41 UTC
    jettero has given you a recommendation that may well solve your problem. This post is more to do with the way you enter passwords in your script. It may be that people looking over your shoulder is not an issue but, if it is, this is a way to stop the password being echoed to the screen. It uses the Term::ReadKey CPAN module. I've never tried to enter two succesive passwords but I don't think you need to reset the ReadMode to 'normal' then back to 'noecho' between them.

    use Term::ReadKey; ... print "enter user1 password: "; ReadMode 'noecho'; $PASS = ReadLine 0; print "enter device enable password: "; $ENABLE = ReadLine 0; ReadMode 'normal'; ...

    I hope this is of interest.

    Cheers,

    JohnGG

      Atually that was a concern, just not one I was going to address immediatly, but the point is well taken. Thanks much, it will be very usefull