rsync mengeluh tentang `missing trailing-" `dalam skrip Bash

13

Mencoba rsync file dari satu server ke yang lain dalam sesi layar. Alih-alih menulis perintah panjang setiap kali, saya memutuskan untuk memasukkan skrip Bash. Namun, ketika saya menjalankannya, saya mendapatkan Missing trailing-" in remote-shell command.kesalahan.

Ingin tahu apa yang salah dalam naskah.

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]

Script menggemakan apa yang akan dilakukan pertama dan kemudian menjalankan perintah. Di bawah ini adalah tumpukan skrip saya:

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

Jawaban:

23

Jawaban singkat: lihat BashFAQ # 050 .

Jawaban panjang: masalah yang Anda hadapi adalah bahwa menanamkan kutipan dalam variabel tidak berfungsi seperti yang Anda pikirkan. Secara khusus, tanda kutip diuraikan sebelum variabel diganti, jadi jika nilai variabel termasuk tanda kutip, sudah terlambat bagi mereka untuk bekerja dengan benar. Ketika Anda mengatur RSYNCOPT="--rsh=\"ssh -p 10022 -c des\" ..."dan kemudian menggunakan ${RSYNCOPT}dalam baris perintah, tanda kutip dalam variabel tidak diuraikan, mereka hanya diperlakukan sebagai karakter normal. Jadi, daripada perintah rsync menerima parameter tunggal --rsh=ssh -p 10022 -c des, menerima 5: --rsh="ssh, -p, 10022, -c, dan des". Karena perintah --rsh berisi kutipan tunggal (tidak cocok), Anda mendapatkan kesalahan.

Untuk melihat apa yang terjadi dengan lebih baik, gunakan set -xuntuk membuat shell mencetak setiap perintah sebelum menjalankannya (sehingga Anda dapat melihat apa yang sebenarnya terjadi), atau ganti dengan echo ${whatever}(yang sangat menyesatkan) dengan printf "%q " ${whatever}; echo.

Ada beberapa cara untuk mengatasi ini. Pertama adalah menghindari mencoba untuk menyimpan RSYNCOPT(dan mungkin hal-hal lain juga) dalam variabel di tempat pertama. Lain adalah untuk menyimpan RSYNCOPTsebagai array (yang dapat melacak batas kata tanpa ada kebingungan ini) daripada string sederhana.

Untuk mencetak perintah sebelum menjalankannya, gunakan set -xsebelum perintah rsync dan atur + x setelah untuk mematikannya, atau gunakan sesuatu seperti printfperintah yang saya sebutkan di atas (perhatikan bahwa ia mencetak ruang nyasar setelah perintah, tetapi ini biasanya tidak ' tidak masalah).

Inilah pendekatan 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}
Gordon Davisson
sumber
Terima kasih telah mengarahkan saya ke arah yang benar, lagi pula, melihat sekilas ke tautan yang Anda berikan meyakinkan saya bahwa suatu fungsi lebih mudah dibaca (atau setidaknya menjadi demikian ketika diformat dengan benar): 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} (Saya tahu, ini cukup lama, tetapi masih satu dari tautan pertama saat mencari "Missing trailing-" in remote-shell command ")
Francesco Marchetti-Stasi
6

Labirin tanda kutip lolos dan tidak terhindar dalam kebingungan Anda $RSYNCOPTsih dari saya; Saya tidak terkejut bahwa ini membingungkan rsync, dan / atau ssh, dan / atau shell lokal atau remote.

Mungkin ada cara untuk membuatnya bekerja dengan menambahkan atau menghapus garis miring terbalik, tetapi saya menyarankan solusi berikut ini sebagai gantinya:

Menggantikan:

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

oleh:

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

Saya mencoba versi skrip Anda yang sedikit disederhanakan di sistem saya dan mendapat pesan kesalahan yang sama dengan yang Anda lakukan; solusi ini memperbaikinya.

Keith Thompson
sumber
1

Menggunakan file konfigurasi ssh juga merupakan opsi yang valid. Inilah yang dapat Anda masukkan / tambahkan ke ~/.ssh/configfile Anda :

Port 10022
Cipher des

Anda juga dapat memfilter parameter ini dengan host jarak jauh dengan menambahkan baris-baris ini dengan Host xyz.domain.whateverdan membuat indentasi:

Host 192.168.1.15
    Port 10022
    Cipher des
Benoit Duffez
sumber