rsync บ่นเกี่ยวกับ `trailing ที่หายไป - '' ในสคริปต์ Bash


10

กำลังพยายาม rsync ไฟล์จากเซิร์ฟเวอร์หนึ่งไปยังเซิร์ฟเวอร์อื่นในเซสชันหน้าจอ แทนที่จะเขียนคำสั่งแบบยาวทุกครั้งฉันตัดสินใจใส่ Bash script อย่างไรก็ตามเมื่อฉันเรียกใช้ฉันได้รับ Missing trailing-" in remote-shell command. ความผิดพลาด

สงสัยว่าเกิดอะไรขึ้นในสคริปต์

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]

สคริปต์สะท้อนสิ่งที่จะทำก่อนจากนั้นจึงเรียกใช้คำสั่ง ด้านล่างเป็นสคริปต์ของฉัน:

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

คำตอบ:


20

คำตอบสั้น ๆ : ดู BashFAQ # 050 .

คำตอบยาว ๆ : ปัญหาที่คุณมีคือการใส่เครื่องหมายคำพูดในตัวแปรไม่ทำงานตามที่คุณคิด โดยเฉพาะการแยกเครื่องหมายคำพูดก่อนที่จะเปลี่ยนตัวแปรดังนั้นหากค่าของตัวแปรมีเครื่องหมายคำพูดอยู่สายเกินไปที่จะให้พวกเขาทำงานได้ถูกต้อง เมื่อคุณตั้งค่า RSYNCOPT="--rsh=\"ssh -p 10022 -c des\" ..." จากนั้นใช้ ${RSYNCOPT} ในบรรทัดคำสั่งเครื่องหมายคำพูดในตัวแปรจะไม่ถูกแยกวิเคราะห์คำเหล่านั้นจะถือว่าเป็นอักขระปกติ ดังนั้นแทนที่จะใช้คำสั่ง rsync ที่ได้รับพารามิเตอร์เดียว --rsh=ssh -p 10022 -c desจะได้รับ 5: --rsh="ssh, -p, 10022, -cและ des". เนื่องจากคำสั่ง --rsh มีเครื่องหมายคำพูดเดียว (ไม่ตรงกัน) คุณจะได้รับข้อผิดพลาด

หากต้องการดูว่าเกิดอะไรขึ้นดีกว่าใช้อย่างใดอย่างหนึ่ง set -x เพื่อให้เชลล์พิมพ์แต่ละคำสั่งก่อนดำเนินการ (เพื่อให้คุณสามารถเห็นสิ่งที่เกิดขึ้นจริง) หรือแทนที่ echo ${whatever} (ซึ่งทำให้เข้าใจผิดอย่างมาก) ด้วย printf "%q " ${whatever}; echo.

มีหลายวิธีในการแก้ปัญหานี้ หนึ่งคือการหลีกเลี่ยงการพยายามที่จะเก็บ RSYNCOPT (และอาจเป็นอย่างอื่นด้วย) ในตัวแปรในตอนแรก อีกอย่างคือการจัดเก็บ RSYNCOPT เป็นอาร์เรย์ (ซึ่งสามารถติดตามขอบเขตของคำโดยไม่มีความสับสนนี้) แทนที่จะเป็นสตริงธรรมดา

หากต้องการพิมพ์คำสั่งก่อนที่จะดำเนินการให้ใช้ set -x หน้าคำสั่ง rsync และตั้งค่า + x หลังจากปิดหรือใช้สิ่งที่ต้องการ printf คำสั่งที่ฉันระบุไว้ข้างต้น (โปรดทราบว่ามันพิมพ์พื้นที่จรจัดหลังจากคำสั่ง แต่โดยทั่วไปไม่สำคัญ)

นี่คือวิธี 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}

6

เขาวงกตของเครื่องหมายคำพูดที่ใช้ Escape และ unescaped ในตัวคุณ $RSYNCOPT สับสน heck จากฉัน; ฉันไม่แปลกใจเลยว่ามันจะทำให้เกิดความสับสน rsync และ / หรือ ssh และ / หรือเชลล์ท้องถิ่นหรือระยะไกล

อาจมีวิธีทำให้สิ่งนี้ทำงานได้โดยการเพิ่มหรือลบแบ็กสแลช แต่ฉันแนะนำวิธีแก้ปัญหาต่อไปนี้แทน

แทนที่:

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

โดย:

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

ฉันลองใช้สคริปต์เวอร์ชันที่เรียบง่ายเล็กน้อยของคุณในระบบของฉันและได้รับข้อความแสดงข้อผิดพลาดเดียวกันกับที่คุณทำ วิธีแก้ปัญหานี้แก้ไขให้ถูกต้อง


1

ใช้ ไฟล์การกำหนดค่า ssh เป็นตัวเลือกที่ถูกต้อง นี่คือสิ่งที่คุณสามารถใส่ / เพิ่มในของคุณ ~/.ssh/config ไฟล์:

Port 10022
Cipher des

นอกจากนี้คุณยังสามารถ กรองพารามิเตอร์เหล่านี้โดยโฮสต์ระยะไกล โดยการเติมบรรทัดเหล่านี้ด้วย Host xyz.domain.whatever และเยื้องพวกเขา:

Host 192.168.1.15
    Port 10022
    Cipher des
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.