I need to run an rsync task from a perl script. (The code below is part of a larger script and using perl is unavoidable.) Since rsync is being run noninteractively, I'd like to avoid printing the ssh login banner from the server I'm uploading files to. I have seen that using the command rsync -e 'ssh -q'
is the way to do this, and this works from the command line. (Well, I'm using the long option format --rsh='ssh -q'
for readability in the script.)
However, I cannot seem to get this to work from my perl script. Here is the relevant part of the code:
#!/usr/bin/env perl
use strict;
use warnings;
my $src = '/path/to/myfile';
my $dest = 'remote:/path/to/target';
my @rsync_cmd;
# this one works, returns 0
@rsync_cmd = ('rsync', '--archive', '--update', '--rsh=ssh', $src, $dest);
system(@rsync_cmd);
print "Exit code: ", $? >> 8, "\n\n";
# this one doesn't, returns 14
@rsync_cmd = ('rsync', '--archive', '--update', '--rsh=\'ssh -q\'', $src, $dest);
system(@rsync_cmd);
print "Exit code: ", $? >> 8;
The first command works fine and returns 0. The second command returns 14 (Error in IPC code) and gives the following output:
rsync: Failed to exec ssh -q: No such file or directory (2)
rsync error: error in IPC code (code 14) at pipe.c(85) [sender=3.1.1]
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: error in IPC code (code 14) at io.c(226) [sender=3.1.1]
As I said, however, running rsync with --rsh='ssh -q'
from the command line does work fine, so I'm not sure what's going on here. I've tried various other ways of quoting the ssh command:
'--rsh="ssh -q"'
q{--rsh='ssh -q'}
q{--rsh="ssh -q"}
(plus a few more) and all of these give the same exit code (14).
Other things I've tried with no success:
ssh
with /usr/bin/ssh
in case rsync was having trouble finding the ssh binary.-e 'ssh -q'
.RSYNC_RSH
environment variable via $ENV{'RSYNC_RSH'}=q{ssh -q}
.--archive
and --update
options for testing purposes.All of these result in the same exit code, 14. I am at my wits' end, please help.
system(..., "--rsh=ssh -q", ...)
You are using the system LIST
syntax, which already passes each argument uninterpolated to the called program. "--rsh=ssh -q"
from Perl is equivalent to --rsh='ssh -q'
in the shell. The quotes will treat the ssh
and the -q
as part of the same argument to the command, but the quotes themselves will be interpolated away in the shell, so rsync
will receive the argument as --rsh=ssh -q
.