Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

Remote shell via ssh

by BernieC (Scribe)
on Aug 14, 2018 at 22:42 UTC ( #1220350=CUFP: print w/replies, xml ) Need Help??

I've been fighting with Net::SSH2 trying to get it to do simple stuff -- in particular all I needed was for it to be ablet execute commands on the server. I've gotten it all working {the biggest hangup was that, apparently, password auth doesn't work in Net::SSH2 and switching to public_key make things magically work}. Here's the skeleton of a little program that'll execute shell commands:

#!/usr/bin/perl # run shell commands remotely over an SSH connection use strict; use warnings ; use Net::SSH2 ; use constant HOST => "YOURHOST" ; use constant USER => "YOURLOGIN" ; use constant HOSTKEY => "Path to your known_hosts keys file" ; ## To enable the public key login, append your 'pub' key file to the ## authorized_keys file in ~/.ssh on the server use constant PUBLICKEY => "Path to your public key" ; use constant PRIVATEKEY => "path to your private key" ; # Set up the SSH connection my $ssh2 = Net::SSH2->new() ; $ssh2->connect(HOST) or $ssh2->die_with_error ; $ssh2->check_hostkey(tofu => HOSTKEY) or $ssh2->die_with_error ; $ssh2->auth_publickey(USER, PUBLICKEY, PRIVATEKEY) or $ssh2->die_with_error ; $ssh2->auth_ok() ; # Logged in -- now you can execute commands print docmd("cd bin; ls") ; $ssh2->disconnect() ; exit ; # do the command and return the output ## NB: you can only do one command on a channel so we get a channel ## do the command, collect the output and close the channel ## The command must be a fully "punctuated and escaped" shell comman +d. sub docmd { my $chan = $ssh2->channel() or $ssh2->die_with_error ; $chan->exec("($_[0]) 2>&1") ; my $out = ""; while (!$chan->eof) { my $buffer = ""; if (not defined ($chan->read($buffer, 100))) { $ssh2->die_with_error() ; } $out .= $buffer ; } return $out ; }

Replies are listed 'Best First'.
Re: Remote shell via ssh
by hippo (Chancellor) on Aug 15, 2018 at 08:47 UTC
    apparently, password auth doesn't work in Net::SSH2

    Given that there's a method specifically for that and no unsolved reported bugs it would be interesting to know what makes you claim this. Perhaps with an SSCCE?

    PS. Note that I'm not advocating password auth over publickey auth here, just that the former should be every bit as possible as the latter with Net::SSH2.

      In the thread Net:SSH2 channels after a fair bit of going-around I discovered that the reason that I couldn't get a channel was twofold. First, auth_ok lies and second, the auth_password just didn't work. Another poster in the thread said he had similar problems. I didn't pursue it any further: once I switched to publickey all the problems went away {and I turned to other troubles I had in my code :o)}. I believe this was a windows problem -- several folk confirmed that it worked OK on unix. If I get a chance I'll try it again and post more info if I get it.

        BernieC: I was surprised that a basic feature like password authentication wouldn't work. So I tried on a local machine at $work. It worked with the $ssh2->auth_password() for me. After some more looking, I printed out $ssh2->auth_list(), and that gave a clue, which sounded familiar to something I'd read recently. It turned out to have been clarified by what salva (the module's author) already told you in Re^4: Can't get $ssh2->check_hostkey to work: requires keyboard-interactive authentication, but you were using password authentication, which is not the same thing: so you were using the wrong authentication type. The results of my experiment, to make it more explicit:

        #!/usr/bin/env perl use warnings; use strict; use Net::SSH2 ':all'; use Config; my $host = 'REDACTED'; my $username = 'REDACTED'; my $password = 'REDACTED'; print STDERR "__DATA__\n\n__RESULTS__\n"; print STDERR "\$] => $]\n"; print STDERR "$_ => $Config{$_}\n" for qw/archname osname osvers/; print STDERR "\n\nhost at \$work\n"; my $ssh2 = Net::SSH2->new(); my $rv = $ssh2->connect($host) or $ssh2->die_with_error; + print STDERR "\tconnect => $rv\n"; #$rv = $ssh2->check_hostkey(LIBSSH2_HOSTKEY_POLICY_ASK) or $ssh2->die_ +with_error; print STDERR "\tcheck hostkey => $rv\n"; # yes +, I know I should... but not doing this for now; you had trouble, too +... and I trust this local host $rv = $ssh2->auth_list($username) or $ssh2->die_with_error; + print STDERR "\tauth_list => $rv\n"; $rv = $ssh2->auth_password($username, $password) or $ssh2->die_with_er +ror; print STDERR "\tauth_password => $rv\n"; my $chan = $ssh2->channel() or $ssh2->die_with_error; + print STDERR "\tget channel => $rv\n"; $rv = $chan->exec('ls -l') or $ssh2->die_with_error; + print STDERR "\texec ls => $rv\n"; print STDERR "line read: " . $chan->readline(); $rv = $chan->close() or $ssh2->die_with_error; + print STDERR "\tchan close => $rv\n"; $rv = $ssh2->disconnect() or $ssh2->die_with_error; + print STDERR "\tdisconnect => $rv\n"; print STDERR "\n\\n"; $ssh2 = Net::SSH2->new(); $ssh2->connect('') or $ssh2->die_with_error; $rv = $ssh2->auth_list() or $ssh2->die_with_error; + print STDERR "\tauth_list => $rv\n"; $rv = $ssh2->auth_password_interact($username) or $ssh2->die_with_erro +r; print STDERR "\tauth_password_interact => $rv\n"; # this wouldn't work on my strawberry perl: "Non-blocking ReadLine + is not supported on this architecture" __DATA__ __RESULTS__ $] => 5.026002 archname => MSWin32-x64-multi-thread osname => MSWin32 osvers => 10.0.16299.371 host at $work connect => 1 auth_list => publickey,gssapi-with-mic,password auth_password => 1 get channel => 1 exec ls => 1 line read: total 948 chan close => 1 disconnect => 1 auth_list => publickey,keyboard-interactive REDACTED's password? Non-blocking ReadLine is not supported on this ar +chitecture at C:/usr/local/apps/berrybrew/perls/5.26.2_64_PDL/perl/ve +ndor/lib/Net/ line 314.

        Notice: my $work host said "publickey,gssapi-with-mic,password" -- ie, it accepts password authentication. But when I checked, it just accepts "publickey,keyboard-interactive". So the valid complaint is "I tried auth_password() even though the host required auth_password_interact(), and it didn't work.".

        And, I didn't try very many experiments with auth_password_interact(), but the one I showed above showed that "Non-blocking ReadLine is not supported on this architecture", so it might be a valid complaint to say "My host doesn't accept auth_password(); the host claims to accept auth_password_interact(), but trying that on Strawberry didn't seem to work, and gave the error 'Non-blocking ReadLine is not supported on this architecture'". This would be the response I would give to salva's post in the other thread, to flag salva that there's been a response.

        But to claim that "auth_password just didn't work" does not tell the whole, accurate story.

        update:: added Re^5: Can't get $ssh2->check_hostkey to work to ask salva about the ReadLine error on strawberry perl

        edit 2:: added paragraph breaks to make it more readable

        I believe this was a windows problem -- several folk confirmed that it worked OK on unix.

        I see. In that case I will be not be in a position to help you solve it. :-)

        However, if you can verify that it is a problem with the module (even if only on MSWin32), it would be good to raise that as an issue so that it can be fixed by the maintainers.

Re: Remote shell via ssh
by edwyr (Sexton) on Sep 05, 2018 at 15:29 UTC
    Side thought and not a contribution to the code... I'm quite interested in the GNU command "parallel" at the moment which is written in PERL and uses ssh(1).

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: CUFP [id://1220350]
Approved by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (4)
As of 2020-08-10 07:34 GMT
Find Nodes?
    Voting Booth?
    Which rocket would you take to Mars?

    Results (56 votes). Check out past polls.