尝试在屏幕会话中将文件从一台服务器同步到另一台服务器。我决定放入一个 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
,-p
,10022
,-c
和des"
。由于 --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)
你的转义和非转义引号的迷宫$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)
我在我的系统上尝试了一个稍微简化的脚本版本,并得到了与您相同的错误消息;此解决方法纠正了它。