perlinmyveins has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

I am having problems with various ssh modules.

Summary (Edit)

The problem I had with both Net::Perl:SSH and Net::SSH2 is that there seemed to be a limit on size of the input stream. In the case of Net::SSH2, this was 32k.

As it turns out, (Thanks syphilis) this is a limit on each write or print call, not the channel itself, so that breaking the writes down into smaller chunks solves the problem.

I have not tried this with Net::SSH::Perl, but the calling mechanismn is different so its hard to see how one would. In fact the reason I had this problem could be seen as being a legacy of the use of Net::SSH::Perl calling mechanism in my code. I have not tried this with any Win32 system, yet.

Original Post

The requirements (which there is no guarantee are reasonable) are that the Perl script will run under both windows and Linux. Furthermore I will at some time in the future use pp to create an .exe file that will run on the windows machine without the installation of Perl. (Or Net::SSH::Perl or other modules) In certain (rather unusual) circumstances the script may decide that actually it needs to delegate the work to another (Linux) server, and in this situation we would ideally like to have standard in, standard out and standard error all available.

In this situation stdin and stdout would be binary streams not necessarily containing line feeds.

There is no need for interactivity.

So my first idea was to use Net::SSH::Perl and with some difficulty I installed this on both the Linux and the Windows machine. (Active state perl. )

But the problems mounted up here, and the remote process would hang if the standard input was more than 10631 bytes. This was using Ubuntu 10.04 to a machine running Fedora 9. (I gave up on windows at this stage.) I also tried it to the local machine, Ubuntu 10.04, and the same problem occurred, except at a different and amount, about 32k.

So, I googled.

It seems there was a discussion about this issue or something similar and a patch was published. The patch would not install on my sources, but I was able to make the changes manually. It changed the size at which it happened by a few bytes, but otherwise had no effect. I removed the patch.

The patch was this one here. http://cpanforum.com/threads/873. It sounds like this really is the problem. The solver does not sound to confident about the patch working. BUT, this was a 2005 thread, with the last comment in 2008, are we really saying that Net::SSH::Perl has been broken since 2005 and nobody can fix it ?

Below was my Net::SSH::Perl code, although not the only variant that I had tried. Note that remote commands such as wc, date etc are used for illustration and as examples of remote commands that do and do not use input.

#!/usr/bin/perl use Net::SSH::Perl; my ($user,$host,$password)=split(/[\@:]/,$ARGV[0]); my $cmd="wc"; my %params=('debug',1 ); my $ssh = Net::SSH::Perl->new($host,%params); $ssh->login($user, $password); my $intext="X" x 10631; # 10631 and bigger fails. # after the patch, +10583 doesnt work, 10582 does. my ($stdout, $stderr, $exit) = $ssh->cmd($cmd,$intext); print "remote output is $stdout\n"; print "remote exit status is $exit\n"; print "remote stderr is $stderr\n";
Then I read a comment saying that Net::SSH::Perl was obsolete and Net::SSH2 is the way to go. Hmmph.

Like Net::SSH::Perl, Net::SSH2 man page does not state weather or not it runs under windows operating systems, this seems to be left as an exercise for the reader. So far as I could see it did not at first but does now. ( As a side note it would be sooo useful if the documentation clearly stated which operating systems the module runs on and which it does not. )

In this case, the process appears to run but no output is transferred. Here is my (rather scrappy) code:

Strangly it works if instead of using wc, you use the command date (which does not read the input) or if you use perl at the remote end to generate arbitrary strings, again without using the input. I have only tried this on localhost.

Since we have the luxary of a file handle here, I expected to be able use the read function, but I also had trouble with this.

#!/usr/bin/perl # use Net::SSH2; use strict; my ($host,$user,$password); ($user,$host,$password)=split(/[\@:]/,$ARGV[0]); my $cmd; $cmd="wc"; #$cmd="date"; #$cmd="perl -e \"print 'Y'x100000\""; my $ssh = Net::SSH2->new(); print STDERR "ssh created\n"; $ssh->connect($host) or die "Unable to connect Host $! \n"; print STDERR "ssh connected \n"; $ssh->auth_publickey($user, '/home/mark/.ssh/id_rsa.pub', #testing on localhost '/home/mark/.ssh/id_rsa' ) or die "Unable to login $!\n"; print STDERR "ssh authenticated\n"; my $intext="X" x 100000; print STDERR "cmd is $cmd\nintext length is ".length($intext)."\n"; my $chan = $ssh->channel() or die "channel creation failed $!"; $chan->blocking(0); binmode($chan); #$chan->shell(); $chan->exec($cmd); print $chan $intext; my $n=0; # while ($n=read($chan,$buf,512)) # while ($n=$chan->read($buf,512)) #{ # print STDERR "$n bytes read\n"; #} my $exit; while (<$chan>) { print $_; $n+=length($_); } $chan->close; $exit=$chan->exit_status(); print "remote exit status is $exit bytes returned is $n bytes\n";
So, my question, Perl Monks is what should I do next. Which modules should I be using, (Perhaps it is none of the above?) and is it really true that both modules are broken ? Or is there something fundamental and stupid wrong with my code?

These seem reasonable and simple things to want to do with Perl, so I cannot see why I am having so much trouble!!

regards,

Mark.

Replies are listed 'Best First'.
Re: Net SSH problems
by PeterPeiGuo (Hermit) on Nov 14, 2010 at 19:14 UTC

    Didn't see any issue with wc, and following code worked.

    use Net::SSH2; use strict; my $ssh = Net::SSH2->new(); $ssh->connect("host") or die "Unable to connect host\n"; $ssh->auth_password("id", "password") or die "Failed to auth\n"; my $channel = $ssh->channel() or die "Channel creation failed\n"; $channel->exec("wc *"); while (<$channel>) {print;}

    Peter (Guo) Pei

      Ah, but the point of my post is that a command that "needs" input, like wc which counts bytes from the standard input , does not work while a command like date, which needs no input and will not look at it even if you give it some, works.

      I do not know what you expect wc * to do - on my system it prints a message about invalid option. The point is that if you provide an invalid option it will not look for input, and in any case your code does not provide any, so that I would expect the command to work! (That is execute and print an error message!)

        Here is how you can do it, the key is send_eof():

        use Net::SSH2; use strict; my $ssh = Net::SSH2->new(); $ssh->connect("curry") or die "Unable to connect host\n"; $ssh->auth_password("aabchts4", "doneit") or die "Failed to auth\n"; my $channel = $ssh->channel() or die "Channel creation failed\n"; $channel->exec("wc"); $channel->write("abc def\n"); $channel->write("abc def\n"); $channel->send_eof(); while (<$channel>) {print;}

        Peter (Guo) Pei

Re: Net SSH problems
by syphilis (Archbishop) on Nov 15, 2010 at 01:53 UTC
    $chan->blocking(0);

    As regards your 2nd script, to get it working with the 'date' command on Win32 (connecting to a local linux host), I had to specify $chan->blocking(1);

    I didn't get it to work with the 'wc' command (and didn't have time to persevere). However, PeterPeiGuo's script worked fine for that command.

    I was a little surprised that I was able to get anywhere with either of these scripts, as last time I tried using the while (<$chan>){...} approach on Win32 I couldn't get it to work at all. Maybe it's something that has been fixed in recent versions of Net::SSH2 - I'll have to sit down and try to make sense of all of this when I get a chance.

    Cheers,
    Rob
      Yes, I agree, blocking(1) (supposed to be the default in fact) does seem to be needed. And I could live with that of course, but this does not fix the other problems.
Re: Net SSH problems
by Khen1950fx (Canon) on Nov 15, 2010 at 12:49 UTC
    Net::SSH::Perl seems to work for me.
    #!/usr/bin/perl use strict; no warnings; use Net::SSH::Perl; use constant HOST => 'localhost'; use constant USER => 'user'; use constant PASS => 'password'; use constant CMD => 'wc'; my $ssh = Net::SSH::Perl->new( HOST, protocol => 2, debug => 1, ); $ssh->login(USER, PASS); my $intext = 'X' x 10632; my ($stdout, $stderr, $exit) = $ssh->cmd(CMD, $intext); print "remote output is: ", $stdout, "remote stderr is: ", $stderr, "\n", "remote exit status is: ", $exit, "\n";
      Could I ask you to try it also with a value considerably larger than 32k, say 100k. There is some evidence that the particular threshold-of-malfunction may be system dependent, on the remote system?

      Thanks very much for your help.

        On my system, there's a limit of 32768. This will explain it better than I can. As I understand it, you can reset the limit.