rsync queixando-se de 'missing trailing-' em um script Bash

10

Tentando rsync arquivos de um servidor para outro em uma sessão de tela. Em vez de escrever o longo comando toda vez, decidi colocar um script Bash. No entanto, quando eu o executo, recebo um erro Missing trailing-" in remote-shell command. .

Perguntando o que está errado no script.

[email protected]:~# /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 [email protected]:/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]

O script faz eco do que ele fará primeiro e depois executa o comando. Abaixo está um despejo do meu script:

#!/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}
    
por HanSooloo 06.11.2011 / 01:53

3 respostas

20

Resposta curta: veja BashFAQ # 050 .

Resposta longa: o problema que você está tendo é que a inserção de cotações em variáveis não funciona da maneira que você acredita. Especificamente, as cotações são analisadas antes que as variáveis sejam substituídas. Assim, se o valor de uma variável incluir cotações, é muito tarde para que elas funcionem corretamente. Quando você define RSYNCOPT="--rsh=\"ssh -p 10022 -c des\" ..." e, em seguida, usa ${RSYNCOPT} em uma linha de comando, as aspas da variável não são analisadas, elas são tratadas apenas como caracteres normais. Portanto, em vez de o comando rsync receber um único parâmetro --rsh=ssh -p 10022 -c des , ele recebe 5: --rsh="ssh , -p , 10022 , -c e des" . Como o comando --rsh contém uma única citação (sem correspondência), você recebe um erro.

Para ver o que está acontecendo melhor, use set -x para fazer o shell imprimir cada comando antes de executá-lo (para que você possa ver o que realmente está acontecendo) ou substitua o echo ${whatever} (que é altamente enganoso) por printf "%q " ${whatever}; echo .

Existem várias maneiras de resolver isso. Uma é evitar a tentativa de armazenar RSYNCOPT (e provavelmente outras coisas também) em variáveis em primeiro lugar. Outra é armazenar RSYNCOPT como uma matriz (que pode controlar os limites das palavras sem qualquer confusão) em vez de uma cadeia simples.

Para imprimir o comando antes de executá-lo, use set -x antes do comando rsync e configure + x after para desativá-lo ou use algo como o comando printf listado acima (observe que ele imprime um espaço perdido após o comando, mas isso geralmente não importa).

Veja a abordagem do 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}
    
por 06.11.2011 / 08:39
6

O labirinto de aspas escapadas e sem escape no seu $RSYNCOPT me confunde; Não me surpreende que confunda o rsync e / ou o ssh e / ou o shell local ou remoto.

Pode haver uma maneira de fazer isso funcionar adicionando ou removendo barras invertidas, mas sugiro a seguinte alternativa:

Substituir:

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

por:

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

Eu tentei uma versão um pouco simplificada do seu script no meu sistema e recebi a mesma mensagem de erro que você recebeu; essa solução alternativa corrigiu isso.

    
por 06.11.2011 / 03:11
1

Usar o arquivo de configuração ssh também é uma opção válida. Veja o que você pode colocar / adicionar ao seu arquivo ~/.ssh/config :

Port 10022
Cipher des

Você também pode filtrar esses parâmetros por host remoto < prefixando estas linhas com Host xyz.domain.whatever e identificando-as:

Host 192.168.1.15
    Port 10022
    Cipher des
    
por 22.06.2016 / 11:57

Tags