A system call from my Perl script truncates the address

Viewed 127

I have the following line in a Perl script, that makes a system call:

system("ssh root@10.48.13.20 /usr/sbin/asterisk -rx 'rpt playback 1101 /etc/asterisk/audio/newsfiles/newstonight'");

When the call is made, Perl reports:

ssh: Could not resolve hostname root.48.13.20: Name or service not known

The called computer is on the same network as the one running the script (I can ping it, etc) The problem is that the IP is being truncated. I'm sure it's something stupid I'm doing wrong , maybe like having to escape the "@"?

4 Answers

You have a few answers, but no-one has explained the problem in any detail.

You have a double-quoted string:

"ssh root@10.48.13.20 /usr/sbin/asterisk -rx 'rpt playback 1101 /etc/asterisk/audio/newsfiles/newstonight'"

One of the useful things about double-quoted strings is that Perl will find any variables in them and replace them with the current value of those variables.

You have something in your string that looks like a variable. It's @10. That looks like an array called "10". So Perl tries to insert the contents of that variable in that part of the string. I'm guessing that you don't have an array called @10 in your code - so the variable ends up being replaced with an empty string and you end up with a string that looks like this:

"ssh root.48.13.20 /usr/sbin/asterisk -rx 'rpt playback 1101 /etc/asterisk/audio/newsfiles/newstonight'"

Which is nonsense and just won't work (and also explains the error you're seeing).

There are a few ways to fix this. Firstly you could escape the @ so Perl no longer thinks it's the start of a variable.

"ssh root\@10.48.13.20 /usr/sbin/asterisk -rx 'rpt playback 1101 /etc/asterisk/audio/newsfiles/newstonight'"

But really, I'd say that if this doesn't need to be a double-quoted string (and I don't think it does) you should put it in single quotes. Of course, as you already have single quotes inside your string, you'll have to swap those out for double quotes:

'ssh root@10.48.13.20 /usr/sbin/asterisk -rx "rpt playback 1101 /etc/asterisk/audio/newsfiles/newstonight"'

Another option would be to use the q[...] operator to create a single-quoted string without actually using single quotes:

q[ssh root@10.48.13.20 /usr/sbin/asterisk -rx 'rpt playback 1101 /etc/asterisk/audio/newsfiles/newstonight']

Finally, it's worth pointing out that if you had use strict in your code (and you should always have use strict and use warnings in your code) then it would know that you don't have a variable called @10 and would give you a useful error message and prevent your program from running until you fix it.

Update: I should also mention that Polar Bear's answer is the best approach. Giving system() a list of strings instead of one string will increase security as Perl will run the external program directly, rather than starting a new shell to run it.

Perhaps reading the documentation might help you to avoid some security pitfalls

use strict;
use warnings;

my @args = ( '-l', 'root', 
             '10.48.13.20', 
             "/usr/bin/asterisk -rx 'rpt playback 1101 /etc/asterisk/audio/newsfiles/newstonight'"
           );

system('ssh',@args);

Reference: system, ssh

Use different quotes. Perl is interpreting @10 as an array.

system(q[ssh root@10.48.13.20 /usr/sbin/asterisk -rx 'rpt playback 1101 /etc/asterisk/audio/newsfiles/newstonight']);

If you're attached to the double quotes, you can escape it.

system("ssh root\@10.48.13.20 /usr/sbin/asterisk -rx 'rpt playback 1101 /etc/asterisk/audio/newsfiles/newstonight'");

Quoting is hard!

Let Perl do it for you:

use Net::OpenSSH;

my $ssh = Net::OpenSSH->new(user => 'root', host => '10.48.13.20');

$ssh->system("/usr/sbin/asterisk",
             "-rx",
             "rpt playback 1101 /etc/asterisk/audio/newsfiles/newstonight")
  or die "Remote command failed: ".$ssh->error;
Related