Melarikan ruang di jalur jauh saat menggunakan rsync melalui koneksi SSH jarak jauh

10

Saat menggunakan SSH untuk menghubungkan rsync ke server jauh, bagaimana Anda keluar dari ruang dan semacamnya di jalur jauh? Garis miring terbalik sederhana keluar dari ruang untuk bash prompt lokal, tetapi pada mesin jarak jauh ruang tersebut kemudian dibaca sebagai istirahat di jalan, sehingga menandai ujung jalan itu.

Jadi ketika saya melakukan rsync -avz /path/to/source/some\ dir/ [email protected]:/path/to/dest/some\ dir/apa yang terjadi adalah bahwa server jauh membaca itu sebagai adil /path/to/dest/some/dan karena itu tidak dapat menemukan tujuan itu dari jarak jauh, karena tujuan sebenarnya adalah "beberapa dir" daripada hanya "beberapa".

Jika saya mencoba perintah yang sama dan menghindari backslash dan ruang untuk melewati bash prompt lokal dan mempertahankan backslash untuk server jarak jauh (total tiga backslash:) /path/to/dest/some\\\ dir/, ia memang mengirim backslash ke server jarak jauh, tetapi server jarak jauh kemudian menginterpretasikan path sebagai /path/to/dest/some\/daripada /path/to/dest/some\ dir/masih mengupas ruang dan karakter setelahnya.

Jika saya mencoba untuk membungkus jalan dengan tanda kutip, itu berperilaku cukup banyak dengan cara yang sama, secara efektif memotong jalan di luar angkasa. Jadi itu juga hanya berfungsi untuk melewati bash prompt lokal.

Awalnya saya menggunakan jalur yang memiliki segmen "-" (space-hyphen-space) di dalamnya, dan server jarak jauh mengembalikan kesalahan rsync: on remote machine: -: unknown optionyang merupakan apa yang memulai seluruh upaya pelarian-ruang ini sejak awal.

Jadi apa yang harus saya lakukan untuk mendapatkan ini berfungsi dengan baik dengan server jauh, tanpa harus menghapus spasi atau karakter salah lainnya seperti tanda hubung dari jalur jauh?

purefusion
sumber
1
Coba kutip tunggal & ganda.
jftuga
Javier menyebutkan ini juga, dan akhirnya berhasil, jadi saya menempelkan segmen kode kerja saya sebagai jawaban atas jawabannya.
purefusion
@purefusion Pertimbangkan untuk menandai jawaban Grégory sebagai benar. The -salamat masalah tanpa perlu untuk menerapkan double-melarikan diri secara manual.
m000

Jawaban:

9

Pada mesin inisiator, rsyncmembangun sebuah baris perintah yang memanggil target rsync pada mesin jarak jauh, kemudian mengirimkan baris perintah itu menggunakan ssh .... sebagai string tunggal . String tunggal itu diteruskan ke shell untuk diuraikan, dibagi menjadi argumen dan dieksekusi rsync. Saya tidak tahu mengapa itu dilakukan, alih-alih mengemas argumen (sudah dibelah, diperluas dan tidak dikutip) dalam beberapa wadah biner-aman ke rsync jarak jauh.

Itu berarti bahwa argumen Anda akan diuraikan oleh dua shell yang berbeda, kutip dan kutip kembali sesuai. Biasanya, saya membungkus setiap argumen dengan tanda kutip ganda, dan kemudian seluruh ekspresi pada tanda kutip tunggal. terkadang itu tidak cukup, atau bisa rumit jika Anda ingin ekspresi yang sama digunakan secara lokal dan jarak jauh.

Dalam kasus itu, saya biasanya mengatur beberapa tautan lunak dengan nama ASCII sederhana, tanpa spasi, semua, dan menggunakannya.

Javier
sumber
8
Dan pemenangnya adalah ... kutip tunggal + ganda! Mungkin ini berbeda di setiap server, jadi jika jawaban yang lain tidak berfungsi untuk sebagian orang, mungkin yang ini akan. Inilah kode sukses yang saya gunakan di sisi jauh dari perintah rsync:'[email protected]:"/path/to/dest/some\ dir/"'
purefusion
Sekarang menimbulkan pertanyaan, mengapa INI bekerja (di server saya), tetapi tidak salah satu dari opsi lain (hanya membungkus jalur dengan tanda kutip ganda, atau menggunakan triple-backslash)? Saya menjalankan CentOS 5 jika itu penting.
purefusion
Seharusnya itu tidak perlu. Bagaimana Anda menjalankannya? Apakah Anda menjalankannya menggunakan evalatau melalui panggilan ke suatu fungsi mungkin?
Mikel
Anda tidak menggunakan tanda kutip tunggal plus ganda. Anda menggunakan tanda kutip tunggal ditambah tanda kutip ganda ditambah lolos backslash. TIGA tingkat mengutip. Ini seharusnya tidak perlu. Saya bertanya lagi: Bagaimana Anda menjalankannya ?
Mikel
@ Javier "Saya tidak tahu mengapa itu dilakukan". Agaknya agar ekspansi tilde bekerja.
Mikel
2

Anda berada di jalur yang benar ketika Anda mengatakan:

Jika saya mencoba perintah yang sama dan melarikan diri backslash dan ruang untuk melewati bash prompt lokal dan menjaga backslash untuk server jauh

Inilah cara yang menurut saya paling mudah untuk dilakukan:

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

dan cara ini juga berfungsi.

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

Bisakah Anda memposting output yang tepat dan kesalahan yang Anda lihat?

Bisakah Anda mengganti rsyncdi kedua sisi dengan skrip pembungkus?

$ 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

Kemudian jalankan rsync Anda lagi, dan harus membuktikan bahwa cara melarikan diri ini berfungsi, misalnya

Sisi klien:

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

Sisi server:

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

Dalam contoh di atas, fakta bahwa argumen ke-4 di server ( dir with spaces) semuanya dalam satu baris mengatakan bahwa kutipan bekerja dengan benar.

Jika ini tidak membantu, coba jalankan kembali rsync -v, atau rsync -vv, atau rsync -vvv. Ini akan memberi Anda informasi debug tambahan.

Dua saran konyol lainnya:

  • apakah server lain adalah server Linux, dan apa shell default Anda di sana?
    • mungkin itu memperluas nama file secara berbeda dari yang Anda harapkan
  • apakah Anda lupa menambahkan opsi -aatau -r?
    • Saya tidak tahu tanpa melihat output Anda
Mikel
sumber
Seperti yang disebutkan dalam perincian pertanyaan, saya memang mencoba kedua metode pertama Anda. Mungkin mereka tidak berfungsi di server saya. Saya juga tidak merasa ingin bermain-main dengan skrip wrapper. Saya mencoba untuk menjauh dari meretas / usr / bin / ... Bagaimanapun, cara lain yang lebih spesifik dari kutipan memang bekerja untuk saya, jadi mungkin hanya server saya yang bertindak seperti ini. Saran Anda mungkin masih layak untuk orang-orang di server lain, atau mereka yang tidak menjalankan CentOS, jika OS merupakan bagian dari masalah.
purefusion
Jadi bagaimana Anda mengutipnya untuk membuatnya berfungsi?
Mikel
Anda meninggalkan beberapa detail penting. Silakan kirim perintah yang sebenarnya Anda jalankan, secara penuh.
Mikel
2

Intinya jawaban:

Gunakan -s (protect args) dan lampirkan path Anda dalam tanda kutip:

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

Bekerja dengan spasi atau garis putus-putus.

Grégory Boddin
sumber
Terima kasih! Ini adalah solusi yang tepat, bukan solusi.
m000
-2

Anda bisa menyertakan path Anda dalam tanda kutip.

atx
sumber
1
Seperti yang mungkin Anda lihat dalam detail pertanyaan, saya memang sudah mencoba ini. Namun, jawaban lain menyarankan penggunaan kutipan tertentu, dan itu memang akhirnya berhasil. :)
purefusion
Anda perlu KEDUA kutipan dan garis miring terbalik.
Sridhar Sarnobat