การหลีกเลี่ยงช่องว่างในเส้นทางระยะไกลเมื่อใช้ rsync ผ่านการเชื่อมต่อ SSH ระยะไกล


10

เมื่อใช้ SSH เพื่อเชื่อมต่อ rsync กับเซิร์ฟเวอร์ระยะไกลคุณจะหลีกเลี่ยงช่องว่างและเช่นนั้นในเส้นทางระยะไกลได้อย่างไร แบ็กสแลชแบบง่ายจะหนีพื้นที่สำหรับพรอมต์การทุบตีท้องถิ่น แต่บนเครื่องระยะไกลพื้นที่จะถูกอ่านเป็นตัวแบ่งในเส้นทางดังนั้นการทำเครื่องหมายจุดสิ้นสุดของเส้นทางนั้น

ดังนั้นเมื่อฉันทำrsync -avz /path/to/source/some\ dir/ user@host.tld:/path/to/dest/some\ dir/สิ่งที่เกิดขึ้นก็คือรีโมตเซิร์ฟเวอร์อ่านอย่างนั้น/path/to/dest/some/และเนื่องจากไม่พบปลายทางนั้นจากระยะไกลเพราะปลายทางที่แท้จริงคือ "บางคน" แทนที่จะเป็น "บางคน"

ถ้าฉันลองใช้คำสั่งเดียวกันและยกเว้นเครื่องหมายแบ็กสแลชและช่องว่างเพื่อให้ได้รับพรอมต์แบ็คโลคอลและรักษาแบ็กสแลชสำหรับ/path/to/dest/some\\\ dir/เซิร์ฟเวอร์ระยะไกล จากนั้นตีความเส้นทางเป็น/path/to/dest/some\/มากกว่าที่จะ/path/to/dest/some\ dir/ยังคงทำลายพื้นที่และตัวละครหลังจากนั้น

หากฉันพยายามที่จะปิดเส้นทางด้วยเครื่องหมายคำพูดมันจะทำงานในลักษณะเดียวกันโดยตัดเส้นทางออกจากพื้นที่อย่างมีประสิทธิภาพ ดังนั้นจึงเป็นการง่ายกว่าที่จะผ่าน bash prompt ในพื้นที่

เริ่มแรกฉันใช้พา ธ ที่มีเซ็กเมนต์ "-" (space-hyphen-space) อยู่ในนั้นและรีโมตเซิร์ฟเวอร์ส่งคืนข้อผิดพลาดrsync: on remote machine: -: unknown optionซึ่งเป็นสิ่งที่เริ่มต้นความพยายามในการหลีกเลี่ยงพื้นที่ทั้งหมดในตอนแรก

ดังนั้นฉันต้องทำอย่างไรเพื่อให้การทำงานนี้ถูกต้องกับรีโมตเซิร์ฟเวอร์โดยไม่ต้องลบช่องว่างหรืออักขระผิดพลาดอื่น ๆ เช่นยัติภังค์จากเส้นทางระยะไกล


1
ลองทั้งคำพูดเดี่ยวและคู่
jftuga

Javier พูดถึงสิ่งนี้เช่นกันและมันก็จบลงด้วยการทำงานดังนั้นฉันจึงวางส่วนรหัสการทำงานลงในการตอบกลับคำตอบของเขา
purefusion

@purefusion ลองทำเครื่องหมายคำตอบของGrégoryให้ถูกต้อง ที่-sอยู่ปัญหาโดยไม่จำเป็นต้องใช้การหลบหนีสองครั้งด้วยตนเอง
m000

คำตอบ:


9

บนเครื่องริเริ่มrsyncสร้างขึ้นบรรทัดคำสั่งที่เรียกเป้าหมาย rsync บนเครื่องระยะไกลแล้วส่งบรรทัดคำสั่งที่ใช้ SSH .... เป็นสายเดียว ว่าสายเดียวจะถูกส่งผ่านไปยังเปลือกจะแยก, rsyncแยกออกเป็นข้อโต้แย้งและดำเนินการ ฉันไม่รู้ว่าทำไมถึงทำเช่นนั้นแทนที่จะเก็บอาร์กิวเมนต์ (ที่ได้รับการขยายแล้วขยายและไม่ออก) ในคอนเทนเนอร์ที่ปลอดภัยแบบไบนารีไปยัง rsync ระยะไกล

นั่นหมายความว่าข้อโต้แย้งของคุณจะถูกแยกวิเคราะห์โดยสองเปลือกหอยที่แตกต่างกัน, ใบเสนอราคาและrequoteตาม โดยปกติแล้วฉันจะสรุปแต่ละอาร์กิวเมนต์ด้วยเครื่องหมายคำพูดคู่และจากนั้นนิพจน์ทั้งหมดในเครื่องหมายคำพูดเดี่ยว บางครั้งมันไม่เพียงพอหรืออาจซับซ้อนหากคุณต้องการให้มีการใช้นิพจน์เดียวกันทั้งในและนอกสถานที่

ในกรณีนั้นฉันมักจะตั้งลิงค์นุ่ม ๆ ด้วยชื่อที่เรียบง่ายไม่มีช่องว่างชื่อ ASCII ทั้งหมดและใช้สิ่งนั้น


8
และผู้ชนะคือ ... คำพูดเดียว + สองครั้ง! อาจจะแตกต่างกันไปในเซิร์ฟเวอร์ทุกเครื่องดังนั้นหากคำตอบอื่น ๆ ใช้ไม่ได้กับบางคน นี่คือรหัสที่ประสบความสำเร็จที่ฉันใช้ในด้านระยะไกลของคำสั่ง rsync:'user@host.tld:"/path/to/dest/some\ dir/"'
purefusion

ตอนนี้ขอให้คำถามทำไมจึงใช้งานได้ (บนเซิร์ฟเวอร์ของฉัน) แต่ไม่ใช่ตัวเลือกอย่างใดอย่างหนึ่ง (แค่ตัดเส้นทางในเครื่องหมายคำพูดคู่หรือใช้เครื่องหมายแบ็กสแลชสามรายการ) ฉันกำลังใช้งาน CentOS 5 อยู่ถ้านั่นสำคัญ
purefusion

นั่นไม่จำเป็น คุณเป็นอย่างไรบ้าง คุณกำลังใช้งานevalหรือผ่านการโทรไปยังฟังก์ชั่นหรือไม่?
Mikel

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

@ จาเวียร์ "ฉันไม่รู้ว่าทำไมมันถึงทำแบบนั้น" สมมุติว่าการขยายตัวของตัวหนอนทำงานได้
Mikel

2

คุณมาถูกทางเมื่อคุณพูดว่า:

ถ้าฉันลองใช้คำสั่งเดียวกันและหลบหนีแบ็กสแลชและช่องว่างเพื่อให้ผ่าน bash prompt ในระบบและรักษาแบ็กสแลชสำหรับเซิร์ฟเวอร์ระยะไกล

นี่เป็นวิธีที่ง่ายที่สุดที่ฉันจะทำได้:

rsync -av dir\ with\ spaces/ server.tld:"dir\ with\ spaces"

และวิธีนี้ใช้ได้เช่นกัน

rsync -av dir\ with\ spaces/ server.tld:dir\\\ with\\\ spaces

คุณสามารถโพสต์ผลลัพธ์ที่แน่นอนและข้อผิดพลาดที่คุณเห็นได้หรือไม่?

คุณสามารถแทนที่rsyncทั้งสองด้านด้วยสคริปต์ตัวแรปเปอร์ได้หรือไม่?

$ sudo su -
# cd /usr/bin
# mv rsync rsync.real
# cat <<'EOF' >rsync
#!/bin/bash
logfile=/home/yourname/rsync.log
date >> "$logfile"
i=1
for arg in "$@"; do
    echo "arg $i: $arg" >> "$logfile"
    i=$((i+1))
done

rsync.real "$@"
EOF
# chmod +x rsync

จากนั้นจึงเรียกใช้ rsync ของคุณอีกครั้งและควรพิสูจน์ว่าวิธีการหนีงานเช่นนี้

ด้านลูกค้า:

Sun Feb 13 13:48:12 EST 2011
1: -av
2: dir with spaces/
3: server:dir\ with\ spaces

ฝั่งเซิร์ฟเวอร์:

Sun Feb 13 13:48:13 EST 2011
1: --server
2: -vlogDtpre.iL
3: .
4: dir with spaces

ในตัวอย่างข้างต้นความจริงที่ว่าอาร์กิวเมนต์ที่ 4 บนเซิร์ฟเวอร์ ( dir with spaces) คือทั้งหมดในหนึ่งบรรทัดบอกว่า quoting ทำงานอย่างถูกต้อง

ถ้าเรื่องนี้ไม่ได้ช่วยลองอีกครั้งทำงานrsync -vหรือหรือrsync -vv rsync -vvvมันจะให้ข้อมูลการดีบักเพิ่มเติม

อีกสองข้อเสนอแนะโง่ ๆ :

  • เซิร์ฟเวอร์อื่นเป็นเซิร์ฟเวอร์ Linux และเชลล์เริ่มต้นของคุณคืออะไร
    • บางทีมันอาจขยายชื่อไฟล์ต่างไปจากที่คุณคาดไว้
  • คุณลืมที่จะเพิ่ม-aหรือ-rตัวเลือก?
    • ฉันไม่สามารถบอกได้หากไม่เห็นผลลัพธ์ของคุณ

ตามที่กล่าวไว้ในรายละเอียดของคำถามฉันได้ลองทั้งสองวิธีแรกของคุณแล้ว บางทีพวกเขาอาจไม่ทำงานบนเซิร์ฟเวอร์ของฉัน ฉันไม่รู้สึกสับสนกับสคริปต์ตัวห่อหุ้ม ฉันพยายามอยู่ห่าง ๆ จากการแฮ็ก / usr / bin / ... ไม่ว่าในกรณีใดวิธีการอ้างอิงที่เจาะจงกว่านี้ก็ใช้ได้ผลกับฉันดังนั้นบางทีมันอาจเป็นแค่เซิร์ฟเวอร์ของฉันที่ทำหน้าที่นี้ คำแนะนำของคุณอาจยังคงใช้งานได้สำหรับผู้ใช้บนเซิร์ฟเวอร์อื่น ๆ หรือผู้ที่ไม่ได้ใช้งาน CentOS หากระบบปฏิบัติการเป็นส่วนหนึ่งของปัญหา
purefusion

แล้วคุณอ้างมันอย่างไรเพื่อให้มันใช้งานได้?
Mikel

คุณกำลังออกรายละเอียดที่สำคัญบางอย่าง กรุณาโพสต์คำสั่งจริงที่คุณใช้อยู่เต็ม
Mikel

2

จุดคำตอบ:

ใช้ -s (ป้องกัน args) และใส่พา ธ ของคุณในเครื่องหมายคำพูด:

rsync -savz user@server:"/my path with spaces/another dir/" "/my destination/"

ใช้ได้ทั้งกับช่องว่างหรือขีดกลาง


ขอบคุณ! นี่เป็นวิธีแก้ปัญหาที่เหมาะสมแทนที่จะเป็นวิธีแก้ปัญหา
m000

-2

คุณสามารถใส่เส้นทางของคุณในเครื่องหมายคำพูด


1
อย่างที่คุณอาจเห็นในรายละเอียดของคำถามฉันได้ลองทำสิ่งนี้แล้ว อย่างไรก็ตามคำตอบอีกข้อเสนอแนะการใช้คำพูดเฉพาะและนั่นก็จบลงด้วยการทำงานจริง :)
purefusion

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