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

Here I go. I've been having a lot of problems using Net::SSH2 and I'm trying to find a solution to what I'm doing.

I have a list of servers and a list of commands. I'm executing the commands on 1 server as soon as it goes to the second one it just gives me an error. But recreating the whole Net::SSH2 object does the trick fine. I'm really frustrated because there is no other library out there that works fine and it's fast.

Here is the code that I'm using:

foreach (@{$servers}) { my $server = $_; $logger->debug("Connecting to remote server \"$server\" throug +h ssh2."); if (!$ssh2->connect($server)) { $logger->error("Connecting to remote server: \"$server\" f +ailed."); my ($code, $error_name, $error_string) = $ssh2->error(); print "ERRORS: $code - $error_name - $error_string\n"; exit; } $logger->debug("Authenticating on server $server."); if (!$ssh2->auth_publickey($self->getUsername(), $self->getPub +licKeyPath(), $self->getPrivateKeyPath())) { $logger->error("Authentication failed for username " . $se +lf->getUsername() . " Maybe no public keys were set up on the remote +host ($server). Check the authorized_keys."); exit; } my $pos = 0; foreach (@{$commands}) { my $chan = $ssh2->channel(); $logger->debug("Executing \"$_\" on $server."); $chan->exec($_); my $status = $chan->exit_status(); if (!$status) { while (my $len = $chan->read(my $buff, 1024)) { $result{$server}[$pos] .= $buff; if ($len < 1024) { last; } } } else { $logger->debug("\"$_\" execution failed."); $result{$server}[$pos] = undef; } if (!$chan->close()) { $logger->error("Closing channel to remote server: \"$ +server\" failed."); exit; } $pos++; # Incrementing the position on the array. } $logger->debug("Disconnecting from remote server \"$server\" t +hrough ssh2."); if (!$ssh2->disconnect()) { $logger->error("Disconnecting to remote server: \"$server\ +" failed."); exit; }

This is the error (I get it the second time of the loop on the servers array):

Net::SSH2::Channel::DESTROY perl(3607) malloc: *** mmap(size=3257352192) failed (error code=12) *** error: can't allocate region *** set a breakpoint in malloc_error_break to debug ERRORS: -5 - LIBSSH2_ERROR_KEX_FAILURE - Unable to exchange encryption + keys

Weird thing here is that the server "is the same". The list of servers is the same server twice (just did it for testing purposes).

Some of you will say, why are you not using shell()? Because is too slow if you read char by char (which is the way while(<$channel>) works). I tried using read on a channel with a buffer ($channel->read($buff, 1024)) It doesn't work at all, sometimes I get the output sometimes I don't (very unreliable). So I opted for the exec version of it open a channel for each command.

Your help is really appreciated... i really don't want to use "backticks" with the ssh command to get this done.

Thank you again.

Replies are listed 'Best First'.
Re: Perl and Net::SSH2
by Anonymous Monk on Aug 06, 2008 at 06:28 UTC
      Ok,
      There are two patches for Net::SSH2 I applied one first on a clean extracted tarball:
      Patch for 5.10
      Same error didn't work.
      I tried to apply the new patch on top of the other one:
      better patch with 5.6 support
      Didn't work. So I created a clean directory of the Net::SSH2 tarball applied the patch and now I got:
      Out of memory!
      Nice to see a message there :-)
      So I'm guessing that any of this patches are working for me.
      This patches are for exec or shell? or for some other things?
      Thank you again.
Re: Perl and Net::SSH2
by zentara (Cardinal) on Aug 06, 2008 at 17:12 UTC
    I think you need to create a new ssh2 object for each connection. It would not be very secure if you didn't in my opinion. However, SSH2 may allow it, if you use keys auth. See Net::SSH2 Question - again- Your error "unable to exchange encryption keys" seems to indicate this.

    I'm not really a human, but I play one on earth Remember How Lucky You Are
      I don't think you'll need to create a new object every time (it will lose its purpose as an object). If an open connection is disconnected and new one made each time with even differents users and key pairs and servers the object should be able to perform multiple operations.
      it's giving me an out of memory even when I'm closing the channels and disconnecting.
      So, I'm guessing I'll be using backticks then. :-)
      Thanks everyone for your help.