rsync si lamenta della mancanza di un finale "in uno script Bash


13

Tentativo di risincronizzare i file da un server all'altro in una sessione dello schermo. Invece di scrivere il lungo comando ogni volta, ho deciso di inserire uno script Bash. Tuttavia, quando lo eseguo, viene visualizzato un Missing trailing-" in remote-shell command.errore.

Chiedendosi cosa non va nella sceneggiatura.

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]

Lo script fa eco a quello che farà prima e quindi esegue il comando. Di seguito è riportato un dump della mia sceneggiatura:

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

Risposte:


23

Risposta breve: vedi BashFAQ # 050 .

Risposta lunga: il problema che stai riscontrando è che l'incorporamento delle virgolette nelle variabili non funziona come pensi. In particolare, le virgolette vengono analizzate prima che le variabili vengano sostituite, quindi se il valore di una variabile include virgolette è troppo tardi perché funzionino correttamente. Quando si imposta RSYNCOPT="--rsh=\"ssh -p 10022 -c des\" ..."e quindi si utilizza ${RSYNCOPT}in una riga di comando, le virgolette nella variabile non vengono analizzate, vengono semplicemente trattate come caratteri normali. Così, piuttosto che il comando rsync riceve un singolo parametro --rsh=ssh -p 10022 -c des, riceve 5: --rsh="ssh, -p, 10022, -c, e des". Poiché il comando --rsh contiene una virgoletta singola (senza eguali), viene visualizzato un errore.

Per vedere cosa sta succedendo meglio, utilizzare set -xper fare in modo che la shell stampi ciascun comando prima di eseguirlo (in modo da poter vedere cosa sta realmente accadendo) o sostituire echo ${whatever}(che è altamente fuorviante) con printf "%q " ${whatever}; echo.

Esistono diversi modi per risolverlo. Uno è quello di evitare di provare a memorizzare RSYNCOPT(e probabilmente anche altre cose) nelle variabili in primo luogo. Un altro è quello di memorizzare RSYNCOPTcome un array (che può tenere traccia dei confini delle parole senza alcuna confusione) piuttosto che una semplice stringa.

Per stampare il comando prima di eseguirlo, usa set -xprima del comando rsync e imposta + x dopo per disattivarlo, oppure usa qualcosa come il printfcomando che ho elencato sopra (nota che stampa uno spazio randagio dopo il comando, ma generalmente non lo fa ' non importa).

Ecco l'approccio 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}

Grazie per avermi indicato nella giusta direzione, comunque una rapida occhiata al link che mi hai fornito mi ha convinto che una funzione è più leggibile (o almeno lo diventa quando formattata correttamente): 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} (lo so, è piuttosto vecchio, ma comunque uno dei primi collegamenti quando si cerca "Missing trailing-" nel comando di shell remota ")
Francesco Marchetti-Stasi

6

Il labirinto di virgolette sfuggite e non sfuggite nel tuo mi $RSYNCOPTconfonde il diavolo; Non mi sorprende che confonda rsync, e / o ssh, e / o la shell locale o remota.

Potrebbe esserci un modo per farlo funzionare aggiungendo o rimuovendo le barre rovesciate, ma suggerisco invece la seguente soluzione alternativa:

Sostituire:

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

di:

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

Ho provato una versione leggermente semplificata del tuo script sul mio sistema e ho ricevuto lo stesso messaggio di errore che hai fatto; questa soluzione è stata corretta.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.