rsync phàn nàn về `thiếu dấu vết-" `trong tập lệnh Bash


13

Cố gắng rsync tập tin từ máy chủ này sang máy chủ khác trong một phiên màn hình. Thay vì viết lệnh dài mỗi lần, tôi quyết định đưa vào tập lệnh Bash. Tuy nhiên, khi tôi chạy nó, tôi gặp Missing trailing-" in remote-shell command.lỗi.

Tự hỏi những gì đang xảy ra trong kịch bản.

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]

Kịch bản lặp lại những gì nó sẽ làm đầu tiên và sau đó thực hiện lệnh. Dưới đây là một tập lệnh của tôi:

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

Câu trả lời:


23

Câu trả lời ngắn: xem BashFAQ # 050 .

Câu trả lời dài: vấn đề bạn gặp phải là việc nhúng dấu ngoặc kép vào các biến không hoạt động theo cách bạn nghĩ. Cụ thể, dấu ngoặc kép được phân tích cú pháp trước khi các biến được thay thế, vì vậy nếu giá trị của biến bao gồm dấu ngoặc kép thì quá muộn để chúng hoạt động đúng. Khi bạn đặt RSYNCOPT="--rsh=\"ssh -p 10022 -c des\" ..."và sau đó sử dụng ${RSYNCOPT}trong một dòng lệnh, các trích dẫn trong biến không được phân tích cú pháp, chúng chỉ được coi là các ký tự bình thường. Do đó, chứ không phải là lệnh rsync nhận một tham số duy nhất --rsh=ssh -p 10022 -c des, nó nhận 5: --rsh="ssh, -p, 10022, -c, và des". Vì lệnh --rsh chứa một trích dẫn (chưa từng có), bạn sẽ gặp lỗi.

Để xem những gì đang diễn ra tốt hơn, hãy sử dụng set -xđể tạo shell in từng lệnh trước khi thực hiện nó (để bạn có thể thấy những gì đang thực sự xảy ra) hoặc thay thế echo ${whatever}(rất dễ gây hiểu lầm) bằng printf "%q " ${whatever}; echo.

Có một số cách để giải quyết điều này. Một là tránh cố gắng lưu trữ RSYNCOPT(và có thể cả những thứ khác nữa) vào các biến ở vị trí đầu tiên. Một cách khác là lưu trữ RSYNCOPTdưới dạng một mảng (có thể theo dõi các ranh giới từ mà không có sự nhầm lẫn này) thay vì một chuỗi đơn giản.

Để in lệnh trước khi thực hiện lệnh, hãy sử dụng set -xtrước lệnh rsync và đặt + x sau để tắt hoặc sử dụng một cái gì đó giống như printflệnh tôi đã liệt kê ở trên (lưu ý rằng nó in một không gian đi lạc sau lệnh, nhưng điều này thường không ' vấn đề).

Đây là cách tiếp cận mảng + 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}

Cảm ơn đã chỉ cho tôi đi đúng hướng, dù sao, một cái nhìn nhanh đến liên kết bạn cung cấp đã thuyết phục tôi rằng một chức năng dễ đọc hơn (hoặc ít nhất là nó trở nên như vậy khi được định dạng chính xác): 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} (Tôi biết, điều này khá cũ, nhưng vẫn là một trong số các liên kết đầu tiên khi tìm kiếm "Mất dấu -" trong lệnh shell từ xa ")
Francesco Marchetti-Stasi

6

Mê cung của dấu ngoặc kép thoát ra và không được giải thoát trong bạn $RSYNCOPTlàm tôi bối rối; Tôi không ngạc nhiên khi nó nhầm lẫn rsync, và / hoặc ssh, và / hoặc shell cục bộ hoặc từ xa.

Có thể có một cách để làm cho điều này hoạt động bằng cách thêm hoặc xóa dấu gạch chéo ngược, nhưng tôi đề nghị cách giải quyết sau đây:

Thay thế:

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

bởi:

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

Tôi đã thử một phiên bản đơn giản hóa tập lệnh của bạn trên hệ thống của tôi và nhận được thông báo lỗi giống như bạn đã làm; cách giải quyết này đã sửa nó.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.