rsync скаржиться на `пропущений трейлінг- '' у сценарії Bash


13

Спроба 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}

Відповіді:


23

Коротка відповідь: див. 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 і встановіть + x після, щоб вимкнути її, або скористайтеся чимось на зразок printfкоманди, переліченої вище (зауважте, що вона друкує бродячий простір після команди, але це, як правило, не ' t матерія).

Ось масив + 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} (Я знаю, це досить стара, але все ж одна перших посилань під час пошуку "Відсутній трейлінг-" в команді віддаленої оболонки ")
Франческо Маршетті-Штазі

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.