Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

accessing Cisco via SSH

by Always Improving (Initiate)
on Oct 12, 2010 at 21:10 UTC ( [id://864948]=perlquestion: print w/replies, xml ) Need Help??

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

OK, so I wrote a telnet version and that works, but now we are migrating to SSh and I have (attempted) to modify it to figure out which to use, and be able to use SSH. So far, it works with telnet capable devices, buy still tries to SSH to them as well, and doesn't work with SSH devices. So, technically, it does nothing more than the original telnet script... Hmm.... Anyway, am I missing something small or am I completely off base and need to RTFM?
#!/usr/bin/perl -w ######################################################## # This script will tftp copies of the running config # # of a predetermined list of devices to a tftp server. # # The script will accept as input a text file which is # # a list of device IP addresses and produce a log file # # to list which devices were successfully backed-up. # # -- Written by Russell Gibbons # ######################################################## use Net::Telnet::Cisco; use Net::SSH::Perl; $ENV{'HOME'} = 'c:\strawberry'; $in_file = $ARGV[0]; # This is the filename of the input file with th +e IP addresses open (LOG, ">backup-log.txt") or die " cannot open log file!"; # log f +ile open (LIST, "<$in_file") or die " cannot open $in_file: $!"; # list +of IP addresses while (<LIST>) { chomp; push @ips, $_; # Populate array of IP addresses } close (LIST) or die " cannot close $in_file: $!"; $user = "********"; $pw = "********"; # Most special characters will require a pr +eceeding '\' $tftp_server = 'XX.XX.XX.XX'; # IP address of TFTP Server for(@ips) { $ssh = TRUE; eval { $cs = Net::Telnet::Cisco->new( Host =>$_, Timeout => 45); if ($cs->login( $user, $pw)) # Login { print "Opening Telnet session to $_\n"; $ssh = FALSE; # If telnet worked, no need to ss +h @hostline = $cs->cmd('sh run | inc hostname'); @hostline = split(/ /, $hostline[0]); chomp $hostline[1]; $hostname = $hostline[1]; print $hostname . "\n"; $cs->cmd("copy system:/running-config tftp://$tftp_server/$h +ostname-confg.txt\n\n\n"); print "sent CRT\n"; $cs->close; # Log out of device print LOG $hostname . ' - ' . $_ . ".\n"; } }; # End trying telnet if ($ssh) { eval { $cs = Net::SSH::Perl->new($_); if ($cs->login( $user, $pw)) # login { print "Opening SSH session to $_\n"; ### Seems to fail here, + or on the next line my(@hostline, $stderr, $exit) = $cs->cmd('sh run | inc hostname' +); @hostline = split(/ /, $hostline[0]); chomp $hostline[1]; $hostname = $hostline[1]; print $hostname . "\n"; $cs->cmd("copy system:/running-config tftp://$tftp_server/$h +ostname.txt\n\n\n"); print "sent CRT\n"; $cs->close; # Log out of device print LOG $hostname . ' - ' . $_ . ".\n"; } }; # End trying ssh } } close (LOG);

Replies are listed 'Best First'.
Re: accessing Cisco via SSH
by afresh1 (Hermit) on Oct 12, 2010 at 21:23 UTC

    I would definitely start with use strict. In this case I don't know where you get the TRUE and FALSE constants because those don't normally exist in perl. This means that when $ssh = FALSE then if ($ssh) still evaluates to true.

    As far as "Doesn't work with SSH devices", you weren't very clear on what doesn't work and what sort of errors you are getting from that so I am not sure how much I can help.

    l8rZ,
    --
    andrew
      Thanks for that. I thought those were the T/F keywords in Perl, but I can figure that out I reckon. Unfortunately, the SSH part gives no errors at all. It prints out that it is connecting via SSH, but then nothing after that print actually happens. I *think* it is logging into the devices though, as if I spam 'sh users' on the switch, I can see the account log in and then quickly disappear. I also tried adding some sleep statements after each cmd, but to no avail. I also added print statements after every line in the SSH block to see if any of the statements were executing - I know, that is crude - and only the print before the snippet to snarf the hostname was successful.

      Thanks again

        In this line:
        my(@hostline, $stderr, $exit) = $cs->cmd('sh run | inc hostname');
        gives you all return values in @hostline and nothing in $stderr or $exit. If you are getting logged in, it should be able to run commands. Using print is a very valuable diagnostic tool. I would probably even go as far as making something very simple for testing.

        use strict; use warnings; use Net::SSH::Perl; $ENV{'HOME'} = 'c:\strawberry'; my $ip = 'xxx'; my $user = '********'; my $pw = '********'; # If you use single quotes, only single quotes +will to be escaped with '\' my $cs = Net::SSH::Perl->new($ip); if ($cs->login( $user, $pw)) { print $cs->cmd('sh run | inc hostname'); } else { warn "Unable to login\n"; } $cs->close;
        l8rZ,
        --
        andrew
Re: accessing Cisco via SSH
by VinsWorldcom (Prior) on Oct 13, 2010 at 14:03 UTC

    I too have tried to write an SSH interface to Cisco much like N::T::C (which rocks by the way). Mine was (going to be) Net::SSH::Cisco - until I realized that it was practically impossible as the Net::SSH(::Perl) modules don't really behave the same way as an interactive Net::Telnet session can.

    That said, looks like you're using Windows from the "$ENV{'HOME'} = 'c:\strawberry';" line and there are some issues getting Net::SSH::Perl to work on Windows - use search on this site (Net::SSH::Perl windows) to see some of the nodes dealing with this.

    Your other option is TFTP the configs off the routers/switches with SNMP (instead of an interactive session to issue the "copy run tftp" command). This of course means you need to be running SNMP on the routers/switches (are you?). Have a look at Cisco::Management and Cisco Router Action Performing Perl Script for help with the TFTP via SNMP route (if that's an option).

Re: accessing Cisco via SSH
by Anonymous Monk on Oct 13, 2010 at 10:51 UTC

    You might want to look at Net::Appliance::Session, looks like it may be what you want these days. Ages ago when I went from Telnet to SSH on Cisco devices, I tried to patch up Net::Telnet::Cisco to work with SSH and gave up in utter frustration.

    I ended up using Expect and regular ssh external command. That basic sub-class of Expect has worked quite well over the years for all sorts of devices Cisco, Foundry, Juniper, etc.

    It looks like Net::Appliance::Session supports Telnet/SSH and has sub-classes for various devices. I might take a look at it, but my Expect version ain't broke :)

      It looks like Net::Appliance::Session requires gcc? I am on a windows machine*, so that may be an insurmountable obstacle. Thanks again for all of the replies though

      * - A windows machine, at work, that I already had to fight tooth and nail to get Perl installed on to begin with, due to 'licensing issues' or some such thing. It's not even like I am writing revenue producing code, just trying to automate some mundane processes!!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://864948]
Approved by afresh1
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (6)
As of 2024-04-16 09:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found