rsync 抱怨 Bash 脚本中的“缺少尾随-”

Han*_*loo 14 ssh bash rsync

尝试在屏幕会话中将文件从一台服务器同步到另一台服务器。我决定放入一个 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]
Run Code Online (Sandbox Code Playgroud)

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

#!/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}
Run Code Online (Sandbox Code Playgroud)

Gor*_*son 24

简短回答:参见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了解正在发生的事情,请在执行每个命令之前使用让 shell 打印每个命令(这样您就可以看到真正发生的事情),或者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 Code Online (Sandbox Code Playgroud)


Kei*_*son 7

你的转义和非转义引号的迷宫$RSYNCOPT让我感到困惑;我对它混淆 rsync、和/或 ssh、和/或本地或远程 shell 并不感到惊讶。

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

代替:

RSYNCOPT="--rsh=\"ssh -p 10022 -c des\" --rsync-path=\"/opt/bin/rsync\" --inplace --progress -a -vv"
Run Code Online (Sandbox Code Playgroud)

经过:

export RSYNC_RSH="ssh -p 10022 -c des"
RSYNCOPT="--rsync-path=\"/opt/bin/rsync\" --inplace --progress -a -vv"
Run Code Online (Sandbox Code Playgroud)

我在我的系统上尝试了一个稍微简化的脚本版本,并得到了与您相同的错误消息;此解决方法纠正了它。