rsync在Bash脚本中抱怨`缺少尾随-'


13

尝试在屏幕会话中将文件从一台服务器同步到另一台服务器。我决定不是每次都写长命令,而是决定放入一个Bash脚本。但是,当我运行它时,出现Missing trailing-" in remote-shell command.错误。

想知道脚本中出了什么问题。

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]

该脚本回显将首先执行的操作,然后执行命令。以下是我的脚本的转储:

#!/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}

Answers:


23

简短答案:请参阅BashFAQ#050

长答案:您遇到的问题是,在变量中嵌入引号不会像您认为的那样起作用。具体来说,在替换变量之前先对引号进行解析,因此,如果变量的值包含引号,那么它们就无法正常工作。当您设置RSYNCOPT="--rsh=\"ssh -p 10022 -c des\" ..."${RSYNCOPT}在命令行中使用时,不会解析变量中的引号,它们只会被视为普通字符。因此,不是rsync命令接收一个单一的参数--rsh=ssh -p 10022 -c des,它接收5: ,--rsh="ssh-p10022-cdes"。由于--rsh命令包含单引号(不匹配),因此会出现错误。

要查看正在发生的事情,可以set -x使外壳在执行每个命令之前先打印每个命令(这样您就可以看到实际发生的情况),或者将替换echo ${whatever}(这很容易引起误解)printf "%q " ${whatever}; echo

有几种解决方法。首先是要避免尝试将RSYNCOPT变量(可能还有其他事情)存储在变量中。另一个方法是将其存储RSYNCOPT为一个数组(可以跟踪单词边界而不会造成任何混淆),而不是简单的字符串。

要在执行命令之前打印该命令,请set -x在rsync命令之前使用,然后在将其关闭之前设置+ x,或者使用类似printf我上面列出的命令的方式(请注意,它会在命令之后打印一个杂散空间,但这通常不会问题)。

这是array + printf方法:

...
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}

感谢您为我指明了正确的方向,无论如何,只要快速浏览一下您提供的链接,就可以说服我,一个函数更具可读性(或者至少在正确格式化后变得如此):( run_rsync() { /opt/bin/rsync "--rsh=\"ssh -p 10022 -c des\" --rsync-path=\"/opt/bin/rsync\" --inplace --progress -a -vv" $1 $2 } run_rsync ${SOURCE} ${REMOTE_USER}${REMOTE_HOST}${REMOTE_BASE}${REMOTE_TARGET} 我知道,这已经很老了,但仍然是一个远程外壳命令中搜索“ Missing tailing-”时的第一个链接”)
Francesco Marchetti-Stasi

6

$RSYNCOPT迷惑不解的引号引起的迷宫使我困惑。我对它使rsync和/或ssh和/或本地或远程shell感到困惑并不感到惊讶。

可能有一种方法可以通过添加或删除反斜杠来使其正常工作,但我建议采用以下解决方法:

更换:

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

通过:

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

我在系统上尝试了稍微简化的脚本版本,并得到了与您相同的错误消息。此解决方法已将其更正。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.