Subject: | channel->read problems with exec and shell |
I have encountered two problems with reading output from channels.
The first is that shell channels return undef from reads. the diamond
operator successfully reads from shell channels, but ext_data('merge')
does not appear to work in this case.
The second is that exec channels hang when reading via the diamond
operator, but work fine with explicit read commands. ext_data('merge')
works here.
Attached are files that demonstrate the problem. SSH2Runs.pl should
successfully execute and demonstrate the ext_data('merge') issue.
SSH2Hangs.pl demonstrates the read undef problem, followed by the read
hang.
I am not sure if this is a Net::SSH2 problem or a libssh2 problem, but I
thought I'd start here.
I've also noticed that the placement of a $channel->blocking(0) call
immediately after the creation of a channel is critical if the channel
is to be used for a shell. Perhaps this hint could be added, to the
documentation.
These issues are occurring on Fedora 8 / x86. Please let me know if I
can provide any assistance. I'm not familiar with xs bindings but I have
a serious interest in making this module robust.
Subject: | SSH2Hangs.pl |
#!/usr/bin/perl
use strict;
use warnings;
require 'SSH2Wrapper.pl';
my $ssh;
my $channel;
Net::SSH2->debug(1);
if (1) {
print "***** Test Single Shell With Read *****\n";
$ssh = wrapConnect();
$channel = $ssh->channel() or die 'could not create channel';
$channel->blocking(0); # the placement of this call is critical
$channel->shell();
print $channel "pwd\n";
print "** BROKEN: channel->read returns undef!: **\n";
printOutputSeperate($channel);
print $channel "ls zzzzzzzzz\n";
print "** BROKEN: channel->read returns undef!: **\n";
printOutputSeperate($channel);
undef $ssh;
undef $channel;
}
if (1) {
print "***** Test Multiple Channel Execs With Diamond *****\n";
$ssh = wrapConnect();
$channel = $ssh->channel() or die 'could not create channel';
# $channel->ext_data('normal'); # default
$channel->exec('pwd');
print "** BROKEN: channel->read hangs on poll!: **\n";
printOutputDiamond($channel);
print "I NEVER GET HERE!!\n";
# $channel = $ssh->channel() or die 'could not create channel';
# $channel->ext_data('merge');
$channel->exec('ls zzzzzzzzz');
print "** BROKEN: channel->read hangs on poll!: **\n";
printOutputDiamond($channel);
print "I REALLY NEVER GET HERE!!\n";
}
Subject: | SSH2Wrapper.pl |
#!/usr/bin/perl
use strict;
use warnings;
use Net::SSH2;
my @poll_events = qw(
in
pri
ext
out
);
my @poll_revents = qw(
err
hup
session_closed
nval
ex
channel_closed
listener_closed
);
sub wrapConnect {
my $ssh = Net::SSH2->new();
$ssh->connect('10.245.2.11') or die 'connect failed';
$ssh->auth_publickey('root', '/home/george/.ssh/id_rsa.pub', '/home/george/.ssh/id_rsa')
or die 'Authentication failed';
return $ssh;
}
sub printOutputSeperate($) {
my ($channel) = @_;
my $buffer;
my $string = '';
while ($channel->read($buffer, 512) > 0) {
$string .= $buffer;
}
print "STDOUT: $string\n";
$string = '';
while ($channel->read($buffer, 512, 1) > 0) {
$string .= $buffer;
}
print "STDERR: $string\n";
print "EXIT: " . $channel->exit_status() . "\n";
}
sub printOutputDiamond($) {
my ($channel) = @_;
my $string = '';
$string .= $_ while (<$channel>);
print "HANDLE OUT: $string\n";
print "EXIT: " . $channel->exit_status() . "\n";
}
1;
Subject: | SSH2Runs.pl |
#!/usr/bin/perl
use strict;
use warnings;
require 'SSH2Wrapper.pl';
my $ssh;
my $channel;
Net::SSH2->debug(1);
if (1) {
print "***** Test Single Shell With Diamond *****\n";
$ssh = wrapConnect();
$channel = $ssh->channel() or die 'could not create channel';
$channel->blocking(0); # the placement of this call is critical
$channel->ext_data('merge'); # merge is broken for shell
$channel->shell();
print $channel "pwd\n";
print "** stdout works: **\n";
printOutputDiamond($channel);
print $channel "ls zzzzzzzzz\n";
print "** BROKEN: merged output should show stderr and exit status 1: **\n";
printOutputDiamond($channel);
undef $ssh;
undef $channel;
}
if (1) {
print "***** Test Multiple Channel Execs With Read *****\n";
$ssh = wrapConnect();
$channel = $ssh->channel() or die 'could not create channel';
# $channel->ext_data('normal'); # default
$channel->exec('pwd');
print "** stdout works: **\n";
printOutputSeperate($channel);
$channel = $ssh->channel() or die 'could not create channel';
# $channel->ext_data('merge'); # merge does work here
$channel->exec('ls zzzzzzzzz');
print "** seperate stderr works: **\n";
printOutputSeperate($channel);
}