I try to send command using SSH in my perl script with # but it gets truncated right at #


Input text is :

$message = "Product ID # STK000134"

The SSH command is :

$execute=`ssh -q id@host /usr/message/send -pin $pager_num -message $message`;

What pass through is :

ssh -q id@host /usr/message/send -pin $pager_num -message Product ID 

Instead of :

ssh -q id@host /usr/message/send -pin $pager_num -message Product ID # STK000134

How to I ensure that # and all text behind # will get through?


# starts a comment in the shell. Add quotes:

$message =~ s/\#/\\\#/g;
$execute=`ssh -q id@host /usr/message/send -pin $pager_num -message "'$message'"`;

The backticks invoke a shell. The shell treats the # and everything after it as comment.

You need to properly quote the interpolated values so that the shell will not “get confused” no matter what characters your strings happen to contain (e.g. single quotes, double quotes, backticks, pound signs, dollar signs, backslashes, et cetera).

You might use a helper sub like this:

sub sq ($) {
    # Bourne-style single quote $_[0]
    # e.g.
    #    foo bar    becomes    'foo bar'
    #    a'b        becomes    'a'\''b'

    # The following implementation does not yield the most compact
    # representations, but it is dead simple.
    my $sq = $_[0];
    $sq =~ s/'/'\\''/g;
$execute=`ssh -q id@host /usr/message/send -pin @{[sq $pager_num]} -message @{[sq $message]}`;

If you do not care for all the noise in the middle of your command string, then you can use some extra variables:

my $sq_pager_num = sq $pager_num;
my $sq_message = sq $message;
$execute=`ssh -q id@host /usr/message/send -pin $sq_pager_num -message $sq_message`;

But that only solves the problem for the local shell. Because you are using ssh, a shell on the remote system will also interpret your strings. So, you actually need to quote them twice.

my $tsq_pager_num = sq sq $pager_num;
my $tsq_message = sq sq $message;
$execute=`ssh -q id@host /usr/message/send -pin $tsq_pager_num -message $tsq_message`;

As an alternative to using a local shell (and having to quote for it), you can run the local command (ssh) directly by using the 4+ argument form of open:

open CMD, '-|', qw(ssh -q id@host /usr/message/send -pin), sq $pager_num, '-message', sq $message;
{ local $/; $execute = <CMD>; }
close CMD;

use Net::OpenSSH and let it do the quoting for you:

use Net::OpenSSH;

my $ssh = Net::OpenSSH->new('id@host');
my $output = $ssh->capture("/usr/message/send",
                           -pin => $pager_num,
                           -message => $message);
$ssh->error and die "ssh failed: " . $ssh->error;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.