Net::SSH2 scp_put not working!

K

Krishna Chaitanya

Is there a case I'm missing where blocking(0) leads to successful
execution and read of a command through $channel->shell() and setting
blocking(1) makes it hang indefinitely?

I've understood polling and related topics, thanks to all your inputs,
but it defeats me completely why setting blocking(1) would hang any
command forever. What am I missing here conceptually?

Many thanks, everyone, for your edifying words...
 
K

Krishna Chaitanya

Also, can anyone please take this program and execute at their end and
tell me if they succeeded in getting the command output?

#!/usr/bin/perl

use warnings;
use strict;

use Net::SSH2;

my $ssh2 = Net::SSH2->new();

$ssh2->connect(<an IP you can connect to>) or die;

if ($ssh2->auth_password(<username>,<password>)) {
print "Authorization successful\n";
my $chan2 = $ssh2->channel();
$chan2->shell();
$chan2->blocking(1);
print $chan2 "uname -a\n";
print "LINE : $_" while <$chan2>;
$chan2->close();
$ssh2->scp_put(<Path-to-any-file-to-be-scp-ed>) or warn "Could
not scp the file <filename> ";
} else {
print "Authorization failure\n";
}

Thanks again!
 
K

Krishna Chaitanya

The first problem I had was that my server doesn't allow 'password'
auth, it requires 'keyboard' auth. The libssh2 documentation says this
is quite common, so you may want to watch for it.

Thanks, I will.
The second problem is here. It turns out that the ->READLINE and ->GETC
methods on Net::SSH2::Channel require the session to be in non-blocking
mode, but they don't set it themselves, and they don't handle timeouts
properly. I would consider this a fairly serious bug in Net::SSH2.

I had the same feeling when I saw calls to poll in READLINE and GETC
(my assumption - it could be silly - is that poll is used in case of
non-blocking I/O), thanks for confirming. How could we attract the
module maintainer's attention w.r.t this?
If your connection is fast enough that you can always guarantee to get a
new character within 250ms of the last, you can set ->blocking(0) around
all <> calls and it will stop hanging.

Sorry for being thick...can I verify this 250ms thing by checking
response time from a ping? Or is there another way for me?
Also, you have a logic error here I hadn't noticed before. Had the <>
been working properly, it would not have returned undef until the other
end set end-of-file. Since the other end is a shell which is waiting for
another command, that was never going to happen.

Hmm.....point taken. So should I instead be using a series of exec? Is
there no way to tell a shell to let me know it's done with the command
processing (some kind of a command-specific EOF)?

Thanks a lot, Ben.
 
K

Krishna Chaitanya

Also...how did <> manage to get EOF from shell in case of blocking
(0) .... ?
 
G

Gary E. Ansok

The second problem is here. It turns out that the ->READLINE and ->GETC
methods on Net::SSH2::Channel require the session to be in non-blocking
mode, but they don't set it themselves, and they don't handle timeouts
properly. I would consider this a fairly serious bug in Net::SSH2.

If your connection is fast enough that you can always guarantee to get a
new character within 250ms of the last, you can set ->blocking(0) around
all <> calls and it will stop hanging. If a character is late, however,
you will not only get an undef returned from <> when you shouldn't but
you will lose the whole of the line that's been read so far. I would
recommend dropping the tied filehandle interface and using ->read and
->write instead, however that will make finding newlines considerably
harder.

This is one reason I gave up on trying to use Net::SSH2 and went
back to Net::SSH::perl instead. I was running a command that would
not return output quickly enough. With blocking in place, it never
returned. With blocking turned off, I couldn't reliably detect when
the remote command completed -- the readline returned undef any time
there was no output waiting to be read, and I couldn't get detection
of listener_closed or channel_closed to work reliably.

Net::SSH::perl doesn't have the scp functions, but you may be able to
work around that. I use cat >file <<_END_OF_INPUT_ to create remote
files -- this could fail in the general case, of course, but the
set of files I needed to process was restricted enough that I knew
it would work for me.

Gary Ansok
 
G

Gary E. Ansok

Quoth (e-mail address removed) (Gary E. Ansok):

I don't really understand what you were trying to do. If you are running
a remote shell without a pty, you *don't* get any indication that the
command has completed. You certainly don't get EOF: the connection is
still open, waiting for another command. If you need an indication, you
need to either use the ->exec method or arrange to have something
printed after each command has finished. A quick but somewhat dirty way
of doing this is to request a pty, which will cause the remote shell to
start printing prompts.

Well, perhaps I wasn't doing it correctly. I was creating a new
channel and then using $chan->exec($cmd), but was having trouble
getting the complete output and detecting when the remote command
finished. (The remote command could be as simple as a script with
"sleep 2; ls".)

As I mentioned, I had an existing version using Net::SSH::perl, so there
wasn't a massive need to switch over. We were having performance issues,
but ended up solving those by upgrading the bigint libraries (I think
there was some glitch in the installation of the eearlier versions).
I think you want Net::SFTP, which implements the ssh2 sftp functionality
on top of Net::SSH::perl. SFTP is what scp(1) actually uses if it's
running over ssh2.

Thanks for the info -- I'd looked at that in the past, but at the time
we were having performance issues centered on the initial connection,
so only doing one connection was important. (I don't see a way to use
an existing Net::SSH::perl connection in Net::SFTP, or a supported way to
use the connection from Net::SFTP for other uses.) Still, it's something
I'll look at again if I need to update this code.

Gary
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top