Perl telnet to router run commands from file

I have a perl script that is called with a router name command list file and output file. The command file can be very large, up to 3k of commands. At first I dumped the command list file to an array and ran the entire file on the router and captured the output. It worked ok for a command list in the hundreds but not thousands. So I changed it to the below to read each line of the command list and wait for a prompt.

It works well but since I am a perl beginner I was hoping some experienced perl people can have a look and see if this can be done any better.

called like this: perl myscript.pl -r <router_name> -f <command_file> -o <output_file>
 
#!/usr/local/bin/perl
use Net::Telnet;
use diagnostics;
use strict;
use Getopt::Std;
my %opts = ();
getopts('f:o:r:', \%opts);
my $file = $opts{'f'};
my $router = $opts{'r'};
my $output = $opts{'o'};
open PASSFILE, "</home/bin/secure/pass" or die $!;
my $password = <PASSFILE>;
chomp $password;
close PASSFILE;
$password =~ /^\s*([^:]+)\:([^:]+)\s*$/;
my $USERNAME = $1;
my $PASSWORD = $2;
my $t = new Net::Telnet (Timeout=>600,Errmode=>'return');
   $t->max_buffer_length(100000000);
   $t->open($router);
   $t->waitfor('/Telnet password[: ]*/i');
   $t->print("$PASSWORD\n");
   $t->waitfor('/.*\>*/');
   $t->print("enable\n");
   $t->waitfor('/password[: ]*$/i');
   $t->print("$PASSWORD\n");
   $t->waitfor('/.*\#$/');
   $t->print("term length 0\n");
   $t->waitfor('/.*\#$/');
  open CMDS,"<$file" or die $!;
    foreach my $line (<CMDS>) {
     chomp($line);
         $t->print("$line\n");
           my @config = $t->waitfor('/.*\#$/');
           open OUT,">>$output" or die $!;
           foreach my $config (@config) {
           print OUT "$config";
           }
           close OUT;
   }
   close CMDS;
   $t->close;

Nice work, I've seen many posts here asking for something similar so I know others will find this useful.

The 600 sec timeout is a little long - do you encounter issues with some commands taking a long time to finish? I'd try reduce it to give feedback to users quicker, you can extend it again for the command processing part if needed.

Could be useful putting or die tests on all your waitfor() calls to assist debugging if router/prompts are wrong eg:

$t->waitfor('/Telnet password[: ]*/i') or die "No router pass prompt";

When doing these type of things I like to change the PS1 prompt to something more unique to ensure we are matching on the command prompt eg:

$t->print("PS1=READY#  \n");
$t->waitfor('/READY#$/') or die "No command prompt";
1 Like