rsync beschwert sich über "fehlendes Trailing-" in einem Bash-Skript

13

Versuch, Dateien in einer Bildschirmsitzung von einem Server auf den anderen zu synchronisieren. Anstatt jedes Mal den langen Befehl zu schreiben, habe ich beschlossen, ein Bash-Skript einzufügen. Wenn ich es jedoch ausführe, wird eine Missing trailing-" in remote-shell command.Fehlermeldung angezeigt.

Ich frage mich, was im Skript falsch läuft.

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]

Das Skript gibt an, was es zuerst tun wird, und führt dann den Befehl aus. Unten ist ein Speicherauszug meines Skripts:

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

Antworten:

23

Kurze Antwort: siehe BashFAQ # 050 .

Lange Antwort: Das Problem, das Sie haben, ist, dass das Einbetten von Anführungszeichen in Variablen nicht so funktioniert, wie Sie denken. Insbesondere werden Anführungszeichen analysiert, bevor Variablen ersetzt werden. Wenn der Wert einer Variablen also Anführungszeichen enthält, ist es zu spät, um richtig zu funktionieren. Wenn Sie in einer Befehlszeile festlegen RSYNCOPT="--rsh=\"ssh -p 10022 -c des\" ..."und dann verwenden ${RSYNCOPT}, werden die Anführungszeichen in der Variablen nicht analysiert, sondern nur als normale Zeichen behandelt. Anstatt also der rsync Befehl einen einzelnen Parameter empfängt --rsh=ssh -p 10022 -c des, erhält er 5: --rsh="ssh, -p, 10022, -c, und des". Da der Befehl --rsh ein einfaches (nicht übereinstimmendes) Anführungszeichen enthält, wird eine Fehlermeldung angezeigt.

Um zu sehen, was besser läuft set -x, lassen Sie die Shell entweder jeden Befehl drucken, bevor Sie ihn ausführen (damit Sie sehen können, was wirklich passiert), oder ersetzen Sie den Befehl echo ${whatever}(der sehr irreführend ist) durch printf "%q " ${whatever}; echo.

Es gibt verschiedene Möglichkeiten, dies zu lösen. Eine besteht darin, zu vermeiden, dass versucht wird, RSYNCOPT(und wahrscheinlich auch andere Dinge) in Variablen zu speichern . Eine andere Möglichkeit besteht darin, RSYNCOPTals Array (das Wortgrenzen ohne diese Verwirrung verfolgen kann) und nicht als einfache Zeichenfolge zu speichern .

Um den Befehl vor dem Ausführen zu drucken, verwenden Sie entweder set -xvor dem Befehl rsync und setzen Sie danach + x, um ihn auszuschalten, oder verwenden Sie etwas wie den printfoben aufgeführten Befehl (beachten Sie, dass nach dem Befehl ein streunendes Leerzeichen gedruckt wird, dies ist jedoch im Allgemeinen nicht der Fall). egal).

Hier ist der Array + Printf-Ansatz:

...
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}
Gordon Davisson
quelle
Vielen Dank, dass Sie mich in die richtige Richtung gelenkt haben. Trotzdem hat mich ein kurzer Blick auf den von Ihnen bereitgestellten Link überzeugt, dass eine Funktion besser lesbar ist (oder zumindest bei richtiger Formatierung): 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} (Ich weiß, das ist ziemlich alt, aber immer noch eine der ersten Links bei der Suche nach "Missing trailing-" im Remote-Shell-Befehl ")
Francesco Marchetti-Stasi
6

Das Labyrinth von entkommenen und nicht entflohenen Anführungszeichen in Ihrem $RSYNCOPTverwirrt mich zum Teufel; Ich bin nicht überrascht, dass es rsync und / oder ssh und / oder die lokale oder entfernte Shell verwirrt.

Es kann eine Möglichkeit geben, dies durch Hinzufügen oder Entfernen von Backslashes zum Laufen zu bringen, aber ich schlage stattdessen die folgende Problemumgehung vor:

Ersetzen:

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

durch:

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

Ich habe eine leicht vereinfachte Version Ihres Skripts auf meinem System ausprobiert und die gleiche Fehlermeldung wie Sie erhalten. Diese Problemumgehung hat es korrigiert.

Keith Thompson
quelle
1

Die Verwendung der SSH-Konfigurationsdatei ist ebenfalls eine gültige Option. Folgendes können Sie Ihrer ~/.ssh/configDatei hinzufügen / hinzufügen :

Port 10022
Cipher des

Sie können diese Parameter auch nach Remote-Host filtern, indem Sie diesen Zeilen voranstellen Host xyz.domain.whateverund sie einrücken :

Host 192.168.1.15
    Port 10022
    Cipher des
Benoit Duffez
quelle