Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Problems with Net::OpenSSH

by aeaton1843 (Acolyte)
on Nov 22, 2010 at 21:46 UTC ( #873051=perlquestion: print w/ replies, xml ) Need Help??
aeaton1843 has asked for the wisdom of the Perl Monks concerning the following question:

Hi all-

I am a bit stumped. I am trying to log into Cisco routers and switches and grab some output with varying amounts of success. At first I was trying to use the capture function to store the output into an array. That was at best inconsistent. After having read through all of the documentation and finding the very first Q/A, I start trying to call expect inside of OpenSSH. At this point the code, times out trying to match the password prompt. I have tried everything conceivable to match the prompt: $expect->expect($timeout, "Password: ") $expect->expect($timeout, ":") $expect->expect($timeout, '-re', "*:*") etcetera to no avail. I am positive that an exact match prompt for the Cisco router is "Password: ". Would someone mind hitting me with a clue stick? :) Thanks! Code follows:

#!/usr/bin/perl use strict; use warnings; use Net::OpenSSH; use Expect; $| = 1; my $username = '...'; #put yours here my $password = '...'; #put yours here my $enable = '...'; #put yours here my $timeout = 30; my $ip = 'w.x.y.z'; #put yours here my $ssh = Net::OpenSSH->new("$username:$password\@$ip", timeout => 30) +; $ssh->error and die "unable to connect to remote host: ". $ssh->error; my ($pty, $pid) = $ssh->open2pty("show ip arp") or die "unable to run remote command show ip arp"; my $expect = Expect->init($pty); $expect->raw_pty(1); #$expect->debug(2); my $debug and $expect->log_stdout(1); $debug and print "waiting for password prompt\n"; $expect->expect($timeout, "Password: ") or die "expect failed, $expect->exp_error()\n"; $debug and print "prompt seen\n"; $expect->send("$password\n"); $debug and print "password sent\n"; $expect->expect($timeout, "\n") or die "bad password\n"; $debug and print "password ok\n"; while(<$pty>) { print "$. $_" }

Comment on Problems with Net::OpenSSH
Download Code
Re: Problems with Net::OpenSSH
by Anonymous Monk on Nov 22, 2010 at 22:49 UTC
    I see when you're initializing Net::OpenSSH, you are giving it the username and password there. Is it possible that bypasses the password prompt (or makes Net::OpenSSH hide it from you) and just drops you at the command line one you are connected and authenticated?

      Thank you to all especially Salva and the anonymous monk. After I read the comments here again, I went back and did some work. The following code works perfectly! Does anyone know whether or not Net::OpenSSH is ithread safe?

      #!/usr/bin/perl use strict; use warnings; use Net::OpenSSH; use Expect; $| = 1; my $username = ''; my $password = ''; my $enable = ''; my $ip = '10.105.0.62'; my $ssh = Net::OpenSSH->new("$username:$password\@$ip", timeout => 30) +; $ssh->error and die "unable to connect to remote host: ". $ssh->error; my ($pty, $pid) = $ssh->open2pty("show ip arp") or die "unable to run remote command show ip arp"; my $expect = Expect->init($pty); $expect->raw_pty(1); #$expect->debug(2); my $debug and $expect->log_stdout(1); while(<$pty>) { print "$. $_" }
        But your router seems to support commands from SSH without dropping you to the shell. You probably don't need to use Expect at all:
        #!/usr/bin/perl use strict; use warnings; use Net::OpenSSH; $| = 1; my $username = ''; my $password = ''; my $enable = ''; my $ip = '10.105.0.62'; my $ssh = Net::OpenSSH->new("$username:$password\@$ip", timeout => 30) +; $ssh->error and die "unable to connect to remote host: ". $ssh->error; my $out = $ssh->pipe_out("show ip arp") or die "unable to run remote command show ip arp"; while(<$out>) { print "$. $_" }
Re: Problems with Net::OpenSSH
by Khen1950fx (Canon) on Nov 23, 2010 at 07:52 UTC
    Try this. It prompts for a password. It returns true if correct or "Permission denied" if incorrect.
    #!/usr/bin/perl use strict; no warnings; use Expect; use Net::OpenSSH; select STDOUT; $| = 1; select STDERR; $| = 1; my $username = 'root'; my $password = $ARGV; my $ip = 'localhost'; my $timeout = 10; my $debug = 0; my $ssh = Net::OpenSSH->new( "$username\@$ip", strict_mode => 0 ); my ( $pty, $pid ) = $ssh->open2pty("show ip arp") or die "unable to run remote command show ip arp"; my $expect = Expect->init($pty); $expect->raw_pty(1); $debug and $expect->log_user(1); $debug and print "waiting for password prompt\n"; $expect->expect( $timeout, ":" ) or die "expect failed, $expect->exp_error()\n"; $expect->send("$password\n"); while (<$pty>) { print "$. $_"; }

      This code gives me the same error that I was seeing with my test code. The following is the output executing exactly what you have posted with changed IP/username, of course.

      andy@andy-desktop:~/core/arpinfo$ ./test2.pl Password: Password: expect failed, Expect=GLOB(0x2083bb8)->exp_error() Connection to 10.105.0.62 closed by remote host.
Re: Problems with Net::OpenSSH
by salva (Monsignor) on Nov 23, 2010 at 08:42 UTC
    As Anonymous Monk has already told you, the login phase is managed by the module and what you get from open2pty is not the login prompt but a shell on the remote device.

    Anyway, usually, the following hack works:

    my $ssh = Net::OpenSSH->new("$username:$password\@$ip", timeout => 30) +; $ssh->error and die "unable to connect to remote host: ". $ssh->error; my $out = $ssh->capture({stdin_data => "show ip arp\n"});
    It just starts a remote shell, pipes the command through its stdin and captures the output.

    If that doesn't work, you will have to revert to Expect. Running the following one-liner from the command line will allow you to interact with the remote shell as returned by open2pty so you can experiment with it and see what you should expect.

    perl -MNet::OpenSSH -e 'Net::OpenSSH->new(q(USER:PASSWD@HOST))->system +({tty=>1})'

      The hack works except that it doesn't return without issuing control-c. Is there some way around that? Part of the output follows.

      andy@andy-desktop:~/core/arpinfo$ ./test3.pl ^C NetServ_Lab_SW_2#show ip arp Protocol Address Age (min) Hardware Addr Type Interface Internet 4.2.4.1 - 0016.c859.1b41 ARPA Vlan42 Internet 192.168.120.1 - 0016.c859.1b42 ARPA Vlan499 ... ... NetServ_Lab_SW_2# NetServ_Lab_SW_2#andy@andy-desktop:~/core/arpinfo$
        Is there any command you can send the remote box to close the session?

        For instance:

        my $out = $ssh->capture({stdin_data => "show ip arp\nexit\n"});
Re: Problems with Net::OpenSSH
by chrestomanci (Priest) on Nov 23, 2010 at 09:22 UTC

    Will your router accept a public/private key pair for authentication instead of using password based auth?

    A few years ago, I was controling a netapp storage device from perl, and I found that it would maintain a list of authorised public ssh keys. Once I had added my public key to it's keyring, I could then have my perl script connect using a private key, and without the need to handle password prompts. The connection went directly to a shell where typicaly my script would issue one command, capture the output and then dissconnect. This made that part of the script much simpler.

    One issue to be aware of, is that the device I was connecting to did not like it if there was an SSH agent which offered several different keys until one was accepted. If the first key offered was not acceptable the connection got dropped, there was no possibility to try a different key or drop back to password based authentication, so when you test, you should add -a to your ssh command line.

      Oh how I wish they did. Cisco didn't add that functionality until IOS 15.0.1(M1) or so. Most of our routers are still in the 12.x train. I am actually controlling some F5's with Net::SSH in the manner in which you are suggesting. It works very well except for one thing. I wrote this module as a threaded app with ithreads and Net::SSH isn't thread safe. I found thanks to this site that Net::SSH::Perl isn't thread safe either. What I may end up doing is moving all of the Cisco routers into code that uses Net::SSH::Perl and use parent/child forking. I suppose I never really found out whether Net::OpenSSH is thread safe. I went looking for it and never found the information.

        Net::OpenSSH is pure perl and does not use any globals, so it should be thread safe. Though I (BTW, I am the author) have never used it in threaded applications. IIRC, nobody have reported problems related to threads either.

        Anyway, Net::OpenSSH can be used asynchronously, you don't even need threads to handle connecting in parallel to several hosts. Check also Net::OpenSSH::Parallel.

Re: Problems with Net::OpenSSH
by pklausner (Scribe) on Nov 23, 2010 at 14:49 UTC
    If you control many Ciscos, you should consider running Rancid anyway. That comes with clogin, which does what you want.
    (Caveat: Rancid mixes Perl, sh & expect/tcl)

      I use rancid for config gathering among other things for the Cisco side of the network here. I think for what I am trying to do it would be more of a headache to try to tie in Rancid. I am in the middle of a large network redesign and am trying to gather and correlate data; NAT, Layer3 ARP, Layer2 MAC, VRRP/HSRP/GLBP and a handful of other things all living on F5, Cisco, Foundry/Brocade, Juniper, Radware, Extreme, and Secure Computing. Most of these devices are unsupported in RANCID. I thought about it and then realized it might just be easier to start from scratch. No I am not stretching the truth... We really do have that many different vendors in our network. Anyone have an easy button? :)

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://873051]
Approved by Corion
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (6)
As of 2014-09-22 21:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (202 votes), past polls