<?xml version="1.0" encoding="windows-1252"?>
<node id="998671" title="Net::SSH2 command output polling" created="2012-10-12 08:38:27" updated="2012-10-12 08:38:27">
<type id="115">
perlquestion</type>
<author id="749850">
VinsWorldcom</author>
<data>
<field name="doctext">
&lt;p&gt;I have yet another [cpan://Net::SSH2] question that I haven't found a definitive solution to yet.  So here goes.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;BACKGROUND&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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-&gt;blocking(0)) and even the issue where the command output lagged one command behind (binmode($chan)), but only sometimes.&lt;/p&gt;

&lt;p&gt;I'm testing my client to both CentOS and Cisco router with SSH enabled.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;ISSUE&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;I tried:&lt;/p&gt;

&lt;c&gt;
my @poll = ({handle =&gt; $chan, events =&gt; 'in'});
if($ssh2-&gt;poll(250, \@poll) &amp;&amp; $poll[0]-&gt;{revents}-&gt;{in}) {
    print $buf while defined ($len = $chan-&gt;read($buf,512))
}
&lt;/c&gt;

&lt;p&gt;and in a last ditch attempt:&lt;/p&gt;

&lt;c&gt;
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-&gt;read($buf,512))
}
&lt;/c&gt;

&lt;p&gt;Neither above command set fixed the issue.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;QUESTION&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;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).&lt;/p&gt;

&lt;p&gt;&lt;b&gt;SCRIPT&lt;/b&gt;&lt;/p&gt;
&lt;c&gt;
#!/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-&gt;new();

if ($ssh2-&gt;connect($host)) {
    print "[Connected]\n";
    if ($ssh2-&gt;auth_password($user, $pass)) {
        print "[Authenticated]\n";

        # Set up shell for interactive
        my $chan = $ssh2-&gt;channel();
        $chan-&gt;blocking(0); # Needed on Windows
        $chan-&gt;shell();
        #binmode($chan); # Seems to take care of both Unix SSH and Cisco 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-&gt;read($buf,512));

        # START:  Interactive Mode
        my $prompt = "ssh&gt; ";
        my $ssh = Term::ReadLine-&gt;new("SSH");
        $ssh-&gt;ornaments(0);
        while (defined (my $cmd = $ssh-&gt;readline($prompt))) {
            chomp $cmd;
            
            if ($cmd =~ /^\s*$/)        { next } # nothing
            if ($cmd =~ /^\s*exit\s*$/) { last } # exit

            $chan-&gt;write("$cmd\n");

            select(undef,undef,undef,0.2); # or sleep 1
            print $buf while defined ($len = $chan-&gt;read($buf,512))
        }
        # END:  Interactive Mode

        $chan-&gt;close
    } else {
        warn "Authentication failed\n"
    }
} else {
    warn "Unable to connect to host $host: $!\n"
}
&lt;/c&gt;</field>
</data>
</node>
