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

Using Net::SSH2 with Net::Telnet::Cisco

by ryber (Acolyte)
on Jan 13, 2011 at 23:43 UTC ( #882263=perlquestion: print w/ replies, xml ) Need Help??
ryber has asked for the wisdom of the Perl Monks concerning the following question:

I have an application which uses Net::Telnet::Cisco to log in to various network devices, run some commands and parse the output. I have been trying to enhance the script to use SSH, but have run into problems due to the fact that the app uses threads.

I have attempted to do this using Net::Appliance::Session and Net::SSH::Perl, but neither appears to be thread safe. In each case I am able to write a simple test program which works, until I modify it so that the objects are instantiated from within a thread, in which case it consistently fails.

So now I am trying to use Net::SSH2. Does anyone have any experience using Net::SSH2 interactively with cisco devices or integrating it with Net::Telnet? What I would like to do is to pass an open Net::SSH2 connection to Net::Telnet::Cisco using Net::Telnet's fhopen() method. However, while the documentation for Net::SSH2::Channel says it is a tied filehandle, if I try to create one and hand it off to Net::Telnet, say like this (I tried with and without the commented line):

my $chan = $ssh2->channel(); #$chan->shell(); my $conn = Net::Telnet->new(Fhopen => $chan);
I get the following error:
Can't locate object method "FILENO" via package "Net::SSH2::Channel" a +t /usr/lib/perl5/site_perl/5.8.8/Net/Telnet.pm line 560.

Does anyone have any experience of suggestions on this? Also, has anyone have any experience using the Pseudo Terminal available via $chan->pty()? If so, any suggestions on how I may be able to integrate Net::Telnet or Net::Telnet::Cisco using that?

Thanks in advance.

Comment on Using Net::SSH2 with Net::Telnet::Cisco
Select or Download Code
Re: Using Net::SSH2 with Net::Telnet::Cisco
by ryber (Acolyte) on Jan 13, 2011 at 23:56 UTC
    Almost forgot to mention- I am running PERL 5.8.8 on 64 bit Redhat running on VMWare.
      Sorry for the late follow up to this- but better late than never.

      Ultimately I was never able to make this work with threads, and switched back to a forking model which works fine. In addition to this problem, I was experiencing another issue with the threaded model whereby when the PERL process ran out of physical memory it crashed. I am guessing that is a problem with either the OS (RHEL 5.6) or the PERL implementation (v5.8.8 for x86_64).

      In any case, the forking model seems to be the way to go. It has no problem once it reaches the limit of physical memory on the box, and is just as fast if not slightly faster than the threaded version. The app also uses Telnet, so I was able to compare the threaded and forking versions by just disabling the non-threadsafe SSH component.

      I should mention that I was using what is now a pretty old version of Net::Appliance::Session- 1.36. Looks like they are now on version 3, so YMMV.
Re: Using Net::SSH2 with Net::Telnet::Cisco
by tilly (Archbishop) on Jan 14, 2011 at 00:53 UTC
    The FILENO issue that you are encountering is because Net::Telnet is trying to get a fileno that it can hand to C code which doesn't understand Perl filehandles. But it is implemented in Perl so there is no such fileno, and therefore no FILENO method implemented, and therefore you have a problem. That's a non-starter.

    The first option is to stop using threads. This is not as crazy as it sounds. Try replacing threads with forks, and see if it works. If it does, then your thread problems may go away. If they don't go away, then be careful to require the module from within the same "thread" as you instantiate the object and they definitely should go away.

    Another option is to create a standalone process that uses Net::Appliance::Session and Net::SSH::Perl which can be driven from within a thread in your main application. Be warned that this type of network programming usually takes more work than you were planning on.

    The third option I see is to try to debug the thread problems in the original modules. I have no idea how easy or hard that will be. If you're lucky it will be as simple as not using the modules, but instead require them in the thread that you instantiate the objects from.

      Thanks for the response, Tilly. I actually just rewrote this app to use threads instead of fork, which was used in the previous version. I was able to get much greater concurrency with threads than I did with fork() and decreased the run time substantially. So, I really don't want to have to rewrite it again to use fork().

      With both Net::Appliance::Session and Net::SSH::Perl, I have the "use" statement in the subroutine that is called by the thread. In each case, I wrote a very simple program. The first version does not create any threads and just calls the subroutine- that works without an issue. Then I modify it so that the subroutine is called as one or more threads. The threaded versions fail consistently.

      I will post the sample programs with more details tomorrow (when I am on my work machine), but basically the Net::Appliance::Session version fails when Net::Appliance::Session::Transport::SSH forks and runs ssh and then tries to create a new IO::Pty object attached to it (I have since read the IO:Pty is not thread safe). The Net::SSH::Perl version will just crash with a Memory Fault at some point in its execution (I have since read that Math::PARI is not thread safe).

      I thought about trying what you are suggesting, where a separate process is invoked from the threads, but if I do that I may as well just rewrite to use fork().

      Thanks again for your comments (and any more you might have).

        As you can see from the docs below, "use" statements are processed before regular code. So I doubt putting them in the subroutine will accomplish what you want.
        use Module VERSION LIST use Module VERSION use Module LIST use Module use VERSION Imports some semantics into the current package from the named module, generally by aliasing certain subroutine or variable names into your package. It is exactly equivalent to BEGIN { require Module; import Module LIST; } except that Module must be a bareword.
        In 882270 tilly suggested:
        The third option I see is to try to debug the thread problems in the original modules. I have no idea how easy or hard that will be. If you're lucky it will be as simple as not using the modules, but instead require them in the thread that you instantiate the objects from.
        Have you tried ditching "use" and go with "require" like he suggested? Seems like the next course of action to take.

        Elda Taluta; Sarks Sark; Ark Arks

Re: Using Net::SSH2 with Net::Telnet::Cisco
by salva (Monsignor) on Jan 19, 2011 at 12:13 UTC
    That should work:
    use Net::OpenSSH; my $ssh = Net::OpenSSH->new($host); my ($fh, $pid) = $ssh->open2socket(); my $conn = Net::Telnet->new(Fhopen => $fh);
    Though note that Net::Telnet may expect to find a server talking the TELNET protocol at the other side of the connection but the SSH connection will just pass all the data stream to the remote shell unmodified.

      Salva-

      thanks for the suggestion. My one concern is that the CPAN page for Net::OpenSSH states: 'For password authentication, IO::Pty has to be installed'. The problem I am experiencing with Net::Appliance::Session seems to come down to the fact that IO::Pty is (apparently) not thread safe. Have you tried this code in a threaded app?

      Thanks,
      Ryan

        Have you tried this code in a threaded app?

        No, I usually prefer to use processes (via fork) rather than threads, and in that environment IO::Pty has never given me any problem.

        In any case, as IO::Pty is only used on the login phase, you could just use a lock to serialize it so that not more than one thread could be using it at the same time.

        Also, if you really find that IO::Pty is not thread safe, just report it to its maintainers... and if it affects Net::OpenSSH operation I would also like to know!

      Hello. I've tried to use your code
      use Net::OpenSSH; use Net::Telnet; my $ssh = Net::OpenSSH->new('pa:abc@10.0.0.1'); my ($fh, $pid) = $ssh->open2socket(); my $conn = Net::Telnet->new(Fhopen => $fh); my @lines = $conn->cmd("sh ver"); print join "\n";
      But I got message below
      Pseudo-terminal will not be allocated because stdin is not a termina +l. command timed-out at t1.pl line 6
      Could you please give me a more detailed example?
        It seems that Net::Telnet prefers talking through a tty.

        That works for me:

        #!/usr/bin/perl use strict; use warnings; use Net::OpenSSH; use Net::Telnet; $Net::OpenSSH::debug = -1; my $ssh = Net::OpenSSH->new('localhost'); my ($fh, $pid) = $ssh->open2pty(); my $conn = Net::Telnet->new(Fhopen => $fh); my @lines = $conn->cmd("find /tmp"); print @lines; my @lines1 = $conn->cmd("ls"); print "\n\nls:\n", @lines1;
Re: Using Net::SSH2 with Net::Telnet::Cisco
by ryber (Acolyte) on Apr 05, 2012 at 14:03 UTC
    Sorry for the late follow up to this- but better late than never.

    Ultimately I was never able to make this work with threads, and switched back to a forking model which works fine. In addition to this problem, I was experiencing another issue with the threaded model whereby when the PERL process ran out of physical memory it crashed. I am guessing that is a problem with either the OS (RHEL 5.6) or the PERL implementation (v5.8.8 for x86_64).

    In any case, the forking model seems to be the way to go. It has no problem once it reaches the limit of physical memory on the box, and is just as fast if not slightly faster than the threaded version. The app also uses Telnet, so I was able to compare the threaded and forking versions by just disabling the non-threadsafe SSH component.

    I should mention that I was using what is now a pretty old version of Net::Appliance::Session- 1.36. Looks like they are now on version 3, so YMMV.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (5)
As of 2014-08-01 06:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (257 votes), past polls