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


Hi monks,
I am writing a script to telnet into a cisco switch and run mutiple commands e.g sh top,sh traffic etc.
My question is how do i use one object referenc to run multiple commands.
I want the flexibility of reading the commands from a config file.
here is what i have got so far.
$cs is the net::telnet object reference
# Execute the command open( FI ,"< $ciscomm_conf") || die ("Cannot find configuration file c +ontaing commands to be run at $ciscomm_conf:$!"); while(<FI>) { my $ciscommand = $_; if(( $ciscommand !~ m/\#/ ) && ($ciscommand !~ m/^\s+$/)) { @cmd_output = $cs->cmd( String => $ciscommand,Timeout =>60); if (!@cmd_output) { push(@cmd_output," command failed or returned null input +\n"); } } } cose FI;
I even tried reading the file in an array and doing a
foreach $tmp (@cms) { @cmd_output = $cs->cmd( String => $ciscommand,Timeout =>60); }

unfortunately in both cases the @cmd_output array is empty.
If i run only one command without a "while" or "for" the same code works.
Any suggestions
Regards <chimni>

Replies are listed 'Best First'.
Re: Net::Telnet::Cisco usage
by tachyon (Chancellor) on Dec 22, 2003 at 07:20 UTC

    You have some logic errors. ie every time through the loop you are resetting the content of @cmd_output. Try this:

    my $cs = Net::Telnet::Cisco->new(Host => '123.123.123.123'); $cs->login('login', 'password'); my $DEBUG = 1; open( FI, $ciscomm_conf ) || die $!; my( @oks, @fails); while(<FI>) { # remove newline chomp; # skip blank or comment lines next if m/^\s*#/ or m/^\s*$/; my $cmd = $_; $DEBUG && print "Sending $cmd\n"; my @cmd_output = $cs->cmd( String => $cmd,Timeout =>60 ); if ( @cmd_output ) { $DEBUG && print "Recv: @cmd_output\n"; push @oks, [ $cmd, \@cmd_output ]; } else { $DEBUG && print "ERR: " . $cs->errmsg . "\n"; push @fails, [ $cmd, $cs->errmsg ]; } } close FI; $cs->close; use Data::Dumper; print "OK\n", Dumper(\@oks); print "Fail\n", Dumper(\@fails);

    cheers

    tachyon


      Hi Tachyon
      ++++++++ :)
      yes, an array is needed to store success output also.Oversight on my part.
      Two things i learnt from your post
      1 . Usage of next if rather than my ungainly if(pattern) && if(pattern)
      2 . The use of Data::dumper to print what i understand to be a "home made" data structure.
      Thanks for the tips
      regards,
      rajdeep.

        chomp() was the other thing you missed. It may or may not make a difference in this case but lines from files have newlines that you typically don't want.....

        cheers

        tachyon

        The other useful thing is:

        $DEBUG = 1; ..... $DEBUG && print "Well at least I got to here and I can get rid of this + msg by setting \$DEBUG = 0\n";

        cheers

        tachyon

Re: Net::Telnet::Cisco usage
by zengargoyle (Deacon) on Dec 22, 2003 at 07:13 UTC

    this is old and ugly but has been used daily for quite some time. the real version uses another method to get the needed passwords, i've removed that chunk for clarity.

    #!/usr/bin/perl use strict; use warnings; $|++; sub usage { my $n = ($0 =~ s:.*/::, $0); return <<_EOU_; Usage: $n [-e] [-a] router [cmdfile [outfile [errfile]]] -e -- do enable. -a -- append to outfile and errfile. \$ cat >dothis sho inter lo0 sho inter gi3/2 ^D \$ rtrchat -e rtrname dothis interface Loopback0 .... \$ _EOU_ } use Getopt::Std; my %opt; getopts('ea',\%opt); my $rtr = shift @ARGV or die usage; my $if = shift @ARGV; my $of = shift @ARGV if $if; my $ef = shift @ARGV if $of; my $console = 'pass'; my $enable = 'pass'; #print "$rtr $if $of $ef @pw\n"; if ($if) { open(IF,"<$if") or die "open $if: $!"; } else { *IF = *STDIN; } my @ci = <IF>; close(IF); my $rw = $opt{a} ? '>>' : '>' ; chomp @ci; if ($of) { open(OF,"$rw$of") or die "open $of: $!"; } else { *OF = *STDOUT; } if ($ef) { open(EF,"$rw$ef") or die "open $ef: $!"; } else { *EF = *STDERR; } # while (<IF>) { print OF; print EF "foo $_" } use Net::Telnet::Cisco; my $c=Net::Telnet::Cisco->new(Host=>$rtr, Timeout => 45) or die"connect $rtr: $!"; $c->errmode( sub { print EF @_,"\n" } ); $c->login("nobody",$console) or die "login"; $c->enable($enable) or die "enable" if $opt{e}; $c->cmd("term len 0")or die "len"; foreach (@ci) { print OF $c->cmd($_); } $c->close;
Re: Net::Telnet::Cisco usage
by jcpunk (Friar) on Dec 22, 2003 at 07:35 UTC
    I've never used that particular module. But I have used Net::Telnet a bit, and I don't believe the command output works in quite that way. Here is an exert from a script I've got to change passwords for people. Hope it helps, about the only thing of note is $PASSWD is my scalar it contains the path to passwd depending on if its going to solaris, irix, bsd, or linux.
    The line I would point you towards is my($pre,$match) = $shell->waitfor(Match => '/Incorrect password/', this gets the output from the command so I can play with it.
    open(STDERR, ">&STDOUT"); # changes STDERR to STDOUT, lets the p +assword thing actually work.... I think if ($METHOD eq 'telnet') { telnet_login($username, $password, $host, \$shell); # calls ou +t to temerity_lib.pl for the generic telnet log in process. NOTE: $shell is passed by referance # perform the actions we need to accomplish $shell->print($PASSWD); # start changing the password $shell->waitfor('/password:/i') or report_error("password","No + password prompt found");; # make sure it worked $shell->print($password); # send your login password my($pre,$match) = $shell->waitfor(Match => '/Incorrect passwor +d/', Match => '/New password:/') +; # make sure it worked $match =~ /New/ or report_error("password","Not prompted for n +ew password");; $shell->print($new_password); # send new password ($pre,$match) = $telnet->waitfor(Match => '/Bad password/', Match => '/Re-enter new passw +ord:/'); # make sure it worked $match =~ /Re-enter/ or report_error("password","New password +rejected"); $shell->print($new_password); # send new password again $shell->waitfor('/changed/i') or report_error("password","New +password rejected"); # make sure it worked $shell->close; }
    and in case you want it here is telnet login I wish I could offer more assistance.

    jcpunk