10

Попытка 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]

Сценарий повторяет, что он будет делать, а затем выполнил команду. Ниже дамп моего скрипта:

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

3 ответа3

20

Краткий ответ: см. 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 чтобы заставить оболочку печатать каждую команду перед ее выполнением (чтобы вы могли видеть, что на самом деле происходит), либо замените echo ${whatever} (что сильно вводит в заблуждение) на printf "%q " ${whatever}; echo

Есть несколько способов решить эту проблему. Во -первых, во-первых, не пытайтесь хранить RSYNCOPT (и, возможно, другие вещи) в переменных. Другой способ - хранить RSYNCOPT в виде массива (который может отслеживать границы слов без какой-либо путаницы), а не в виде простой строки.

Чтобы напечатать команду перед ее выполнением, либо используйте set -x перед командой rsync и set +x after, чтобы отключить ее, либо используйте что-то наподобие команды printf я перечислил выше (обратите внимание, что после команды она выводит пробелы, но это вообще не имеет значения).

Вот подход массива +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}
6

Лабиринт спасенных и неиспользованных кавычек в вашем $RSYNCOPT сбивает меня с толку; Я не удивлен, что это сбивает с толку rsync, и / или ssh, и / или локальную или удаленную оболочку.

Может быть способ заставить это работать, добавляя или удаляя обратную косую черту, но вместо этого я предлагаю следующий обходной путь:

Заменить:

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"

Я попробовал слегка упрощенную версию вашего скрипта в моей системе и получил то же сообщение об ошибке, что и вы; этот обходной путь исправил это.

1

Использование файла конфигурации ssh также допустимо. Вот что вы можете добавить / добавить в файл ~/.ssh/config :

Port 10022
Cipher des

Вы также можете отфильтровать эти параметры по удаленному хосту , добавив в эти строки Host xyz.domain.whatever и пометив их:

Host 192.168.1.15
    Port 10022
    Cipher des

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .