Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Trying to rsync files from one server to the other in a screen session. Instead of writing the long command every single time, I decided to put in a Bash script. However, when I run it, I get a Missing trailing-" in remote-shell command. error.

Wondering what is going wrong in the script.

root@127.0.0.1:~# /raid/data/module/bin/rbk.sh Movies /raid/data/Movies rsync_target/

/raid/data/module/bin/screen -S Movies 

/opt/bin/rsync --rsh="ssh -p 10022 -c des"\
--rsync-path="/opt/bin/rsync" --inplace --progress -a -vv \
/raid/data/Movies sys@192.168.1.15:/raid/data/rsync_target/

Missing trailing-" in remote-shell command.
rsync error: syntax or usage error (code 1) at main.c(361) [sender=3.0.5]

The script echoes what it will do first and then executed the command. Below is a dump of my script:

#!/bin/bash
SCREEN="/raid/data/module/bin/screen"
SCREENOPT="-S"
SCREEN_TITLE=$1

RSYNC="/opt/bin/rsync"
RSYNCOPT="--rsh=\"ssh -p 10022 -c des\" --rsync-path=\"/opt/bin/rsync\" --inplace --progress -a -vv"

SOURCE=$2

REMOTE_USER="sys@"
REMOTE_HOST="192.168.1.15"
REMOTE_BASE=":/raid/data/"
REMOTE_TARGET=$3

echo ${SCREEN} ${SCREENOPT} ${SCREEN_TITLE}

echo ${RSYNC} ${RSYNCOPT} ${SOURCE} ${REMOTE_USER}${REMOTE_HOST}${REMOTE_BASE}${REMOTE_TARGET}
${RSYNC} ${RSYNCOPT} ${SOURCE} ${REMOTE_USER}${REMOTE_HOST}${REMOTE_BASE}${REMOTE_TARGET}
share|improve this question

2 Answers 2

up vote 8 down vote accepted

Short answer: see BashFAQ #050.

Long answer: the problem you're having is that embedding quotes in variables doesn't work the way you think it does. Specifically, quotes are parsed before variables are replaced, so if a variable's value includes quotes it's too late for them to work right. When you set RSYNCOPT="--rsh=\"ssh -p 10022 -c des\" ..." and then use ${RSYNCOPT} in a command line, the quotes in the variable don't get parsed, they're just treated as normal characters. Thus, rather than the rsync command receiving a single parameter '--rsh=ssh -p 10022 -c des', it receives 5: '--rsh="ssh', '-p', '10022', '-c', and 'des"'. Since the --rsh command contains a single (unmatched) quote, you get an error.

To see what's going on better, either use set -x to make the shell print each command before executing it (so you can see what's really happening), or replace the echo ${whatever} (which is highly misleading) with printf "%q " ${whatever}; echo.

There are several ways to solve this. One is to avoid trying to store RSYNCOPT (and probably other things as well) in variables in the first place. Another is to store RSYNCOPT as an array (which can keep track of word boundaries without any of this confusion) rather than a simple string.

To print the command before executing it, either use set -x before the rsync command and set +x after to turn it off, or use something like the printf command I listed above (note that it prints a stray space after the command, but this generally doesn't matter).

Here's the array+printf approach:

...
RSYNCOPT=(--rsh="ssh -p 10022 -c des" --rsync-path=\"/opt/bin/rsync\" --inplace --progress -a -vv)
...
printf "%q " ${SCREEN} ${SCREENOPT} ${SCREEN_TITLE}
echo

printf "%q " ${RSYNC} "${RSYNCOPT[@]}" ${SOURCE} ${REMOTE_USER}${REMOTE_HOST}${REMOTE_BASE}${REMOTE_TARGET}
echo
${RSYNC} "${RSYNCOPT[@]}" ${SOURCE} ${REMOTE_USER}${REMOTE_HOST}${REMOTE_BASE}${REMOTE_TARGET}
share|improve this answer

The maze of escaped and unescaped quotation marks in your $RSYNCOPT confuses the heck out of me; I'm not surprised that it confuses rsync, and/or ssh, and/or the local or remote shell.

There may be a way to get this to work by adding or removing backslashes, but I suggest the following workaround instead:

Replace:

RSYNCOPT="--rsh=\"ssh -p 10022 -c des\" --rsync-path=\"/opt/bin/rsync\" --inplace --progress -a -vv"

by:

export RSYNC_RSH="ssh -p 10022 -c des"
RSYNCOPT="--rsync-path=\"/opt/bin/rsync\" --inplace --progress -a -vv"

I tried a slightly simplified version of your script on my system and got the same error message you did; this workaround corrected it.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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