VinsWorldcom has asked for the wisdom of the Perl Monks concerning the following question:
I have yet another Net::SSH2 question that I haven't found a definitive solution to yet. So here goes.
BACKGROUND
Windows 7 x64 / Strawberry Perl 5.16.1 / Net::SSH2 0.45 - note that Net::SSH2 comes bundled with Strawberry, I did not compile myself.
I've created a simple SSH client using Net::SSH2 and I can connect fine, I've gotten past the freezing issue on Windows ($chan->blocking(0)) and even the issue where the command output lagged one command behind (binmode($chan)), but only sometimes.
I'm testing my client to both CentOS and Cisco router with SSH enabled.
ISSUE
The issue I see is that if I execute a long command (e.g., 'ls -alR /' on linux, 'show run' on Cisco router) I start to see some output and then just get the prompt back. When I issue the next command, I get the remainder of output from the first long command - or maybe just some of it if it's a really long output.
To my novice mind, it seems to be a buffering problem and I've tried the flush() method of Net::SSH2 to no avail. My other thought is that I need to set $| on the $chan filehandle, which also didn't solve it. My final desperation was to actually read the POD line-by-line and found the poll() method and some Google-ing turned up an example of it's usage.
I tried:
my @poll = ({handle => $chan, events => 'in'}); if($ssh2->poll(250, \@poll) && $poll[0]->{revents}->{in}) { print $buf while defined ($len = $chan->read($buf,512)) }
and in a last ditch attempt:
my ($rin, $rout, $ein, $eout) = ('', '', '', ''); vec($rin, $chan, 1) = 1; # tried $ssh2 and $chan, # but should be: fileno($var) which errors if (select($rout=$rin, undef, $eout=$ein, 5000)) { print $buf while defined ($len = $chan->read($buf,512)) }
Neither above command set fixed the issue.
QUESTION
I'm now thinking it may be due to blocking(0); however, if that isnt' used, Windows just hangs after the connect. How can I get Net::SSH2 to "wait" until all output from a command is printed without just adding an artificially long sleep? Note that I use Net::Telnet to connect to linux and Cisco routers and this isn't an issue - it patiently waits until all output is printed and never seems to chop command output (which I think is the buffering issue).
SCRIPT
#!/usr/bin/perl use strict; use warnings; use Net::SSH2; use Term::ReadLine; my $host = '10.254.254.1'; my $user = 'cisco'; my $pass = 'cisco'; my ($len, $buf); my $ssh2 = Net::SSH2->new(); if ($ssh2->connect($host)) { print "[Connected]\n"; if ($ssh2->auth_password($user, $pass)) { print "[Authenticated]\n"; # Set up shell for interactive my $chan = $ssh2->channel(); $chan->blocking(0); # Needed on Windows $chan->shell(); #binmode($chan); # Seems to take care of both Unix SSH and Cis +co servers # Sometimes needed to "clear", flush() doesn't seem to work # Otherwise, first command does not work select(undef,undef,undef,0.2); # or sleep 1 print $buf while defined ($len = $chan->read($buf,512)); # START: Interactive Mode my $prompt = "ssh> "; my $ssh = Term::ReadLine->new("SSH"); $ssh->ornaments(0); while (defined (my $cmd = $ssh->readline($prompt))) { chomp $cmd; if ($cmd =~ /^\s*$/) { next } # nothing if ($cmd =~ /^\s*exit\s*$/) { last } # exit $chan->write("$cmd\n"); select(undef,undef,undef,0.2); # or sleep 1 print $buf while defined ($len = $chan->read($buf,512)) } # END: Interactive Mode $chan->close } else { warn "Authentication failed\n" } } else { warn "Unable to connect to host $host: $!\n" }
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Net::SSH2 command output polling
by t_rex_joe (Sexton) on Oct 12, 2012 at 18:39 UTC |