Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

SSH and qx

by cbeckley (Curate)
on Mar 13, 2017 at 13:55 UTC ( #1184423=perlquestion: print w/replies, xml ) Need Help??

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

I'm using qx to ssh several admin commands on remote servers. I know I should be using Net::SSH, but the machines involved are legacy. And by legacy, I mean so ancient that we can't install, update, or patch either the OS or anything else.

I really appreciate any time you can spare to sanity check this script. It's currently running and getting the job done, but if you could let me know if I'm doing anything dangerous or if there's a better and/or more stable way of doing it, that would be wonderful.

#!/usr/bin/perl use strict; use warnings; use Data::Dumper; use File::Basename qw(basename); #use Net::OpenSSH; sub ops_do_ssh_qx { my ($cmd) = @_; $cmd->{ssh_cmd} = 'ssh ' . $cmd->{user} . '\@' . $cmd->{host} . ' +\'' . $cmd->{command} . '\'' . ' 2>/dev/null'; $cmd->{output} = qx($cmd->{ssh_cmd}); if ( defined $cmd->{output} ) { $cmd->{cmd_ret_code} = $?; chomp $cmd->{output}; } else { ($cmd->{ssh_ret_code}, $cmd->{ssh_ret_msg}) = (0 + $!, '' . $!); } return $cmd; } my $state = { progname => basename($0), status => 'success' }; my @commands = ( { name => 'command_name1', user => 'user1', host => '', command => 'rsync_command yadda yadda' }, { name => 'command_name2', user => 'user2', host => '', command => 'rsync_command yadda yadda' } ); for my $cmd (@commands) { if ($state->{status} eq 'success') { my $cmd_status = ops_do_ssh_qx($cmd); if ( (!defined $cmd_status->{cmd_ret_code}) or ($cmd_status->{cm +d_ret_code} != 0) ) { $state->{status} = 'failure'; $state->{stack_trace} = $cmd_status; } } } if ($state->{status} ne 'success') { $Data::Dumper::Varname = $state->{progname} . '_state_'; print Dumper($state); exit 1; }


Update: I meant Net::OpenSSH rather than Net::SSH

Replies are listed 'Best First'.
Re: SSH and qx
by haukex (Chancellor) on Mar 13, 2017 at 15:48 UTC

    First of all, the same thing thanos1983 asked: what version of Perl will the script be running on? Net::OpenSSH, which you've commented out, works down to Perl v5.8 and would be the module I'd recommend, even if it may be tricky to install on your legacy system I'd still suggest you give it a try. It looks like it's a pure Perl module.

    The one thing I see is that in the command you construct, if $cmd->{command} contains any characters that would influence the shell quoting (e.g. '), you'll have trouble. If you can, I'd recommend IPC::System::Simple's replacement for qx, capturex. Otherwise, as I wrote about at length here, you might also use piped opens that avoid the shell (also available starting Perl v5.8). If you're on a Perl <5.8, you may have to live with backticks and the potential problems, or you could maybe have a look at String::ShellQuote to alleviate some of those worries.

      Wow, that's an extensive write up on how to avoid backticks. Thank you so much!

Re: SSH and qx
by thanos1983 (Parson) on Mar 13, 2017 at 14:39 UTC

    Hello cbeckley,

    What version of Perl is the legacy OS is running?

    Maybe we can find an old ssh module on cpan, pre installed.

    You can check through cpan terminal if a module is installed like this:

    cpan[1]> m Net::SSH Reading '/home/user/.cpan/Metadata' Database was generated on Mon, 13 Mar 2017 14:17:02 GMT Module id = Net::SSH CPAN_USERID IVAN (Ivan Kohler <>) CPAN_VERSION 0.09 CPAN_FILE I/IV/IVAN/Net-SSH-0.09.tar.gz UPLOAD_DATE 2008-05-14 MANPAGE Net::SSH - Perl extension for secure shell INST_FILE /home/user/perl5/lib/perl5/Net/ INST_VERSION 0.09 cpan[2]> m Net::SSH::Perl Module id = Net::SSH::Perl CPAN_USERID SCHWIGON (Steffen Schwigon <>) CPAN_VERSION 2.09 CPAN_FILE S/SC/SCHWIGON/Net-SSH-Perl-2.09.tar.gz INST_FILE (not installed)

    Hope this helps.

    Seeking for Perl wisdom...on the process of learning...not there...yet!

      Thanks for taking the time to look at this.

      The version of Perl running is v5.12.3. Neither Net::SSH nor NET::OpenSSH, which is what I use elsewhere, are installed. v5.12.3 is good in that it opens some of the options that you and haukex have mentioned. This is the last machine of it's ilk in the environment and due to a number of reasons its retirement keeps getting postponed, and while I'm attempting to work through the resistance facing the installation of even local copies of Perl modules, unless I get permission to install new modules I'm stuck with what's currently installed.


        Net::OpenSSH is a pure Perl module. You just have to copy everything in the lib directory from the module distribution into some directory in the machine and add that directory into @INC to get it working.

        The only possible issue would be that the available ssh could be too old. If that is the case, you can also try Net::SSH::Any, that will happily work with older versions of ssh using the Ssh_Cmd backend.

        Net::SSH::Any is also a pure Perl module that you can install in the same way, just copying the contents of its lib directory.

Log In?

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

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (4)
As of 2020-06-02 18:44 GMT
Find Nodes?
    Voting Booth?
    Do you really want to know if there is extraterrestrial life?

    Results (19 votes). Check out past polls.