bagaimana cara mendapatkan rsync untuk menautkan file identik dengan opsi --link-dest jika file lama sudah ada?

11

Orang mungkin berpikir bahwa --link-destfile yang identik akan berfungsi dalam semua kasus. Tapi itu tidak ketika file itu ada, bahkan jika file sudah ketinggalan zaman / memiliki konten yang berbeda.

Karena ini, dari halaman manual rsync pada --link-dest:

"Opsi ini bekerja paling baik ketika menyalin ke hierarki tujuan kosong, karena rsync memperlakukan file yang ada sebagai definitif (jadi rsync tidak pernah melihat di dir-link-dest ketika file tujuan sudah ada )"

Ini berarti bahwa jika y/fileada sama dengan sumber, dan z/filekedaluwarsa,

rsync -a --del -link-dest=y source:/file z

akan menghasilkan DUA inode (dan dua kali ruang disk) yang digunakan, y/filedan z/file, yang akan memiliki konten dan datestamp yang sama.

Saya menemukan ini karena saya melakukan backup harian pada dasarnya dengan skrip ini dijalankan sekali per hari:

mv $somedaysago $today; 
yest=$today; today=`date +%Y%m%d`;
rsync -avPShyH --del --link-dest=../$yest host:/dirs $today

Karena cadangan saya menjangkau hingga 10 juta file, melakukan rm -rf $olddir; rsync source:$dir newdirakan memakan waktu terlalu lama (terutama ketika hanya 0,5% dari file berubah per hari, menyebabkan penghapusan dan pembuatan entri 10M dir hanya untuk menangani 50 ribu file baru atau yang diubah, yang akan membuat saya cadangan tidak lengkap pada waktunya untuk hari berikutnya).

Inilah demo situasi:

aadalah sumber kami, 1melalui 4cadangan-cadangan bernomor kami:

$ mkdir -p 1 2; echo foo > 1/foobar; cp -lrv 1/* 2
`1/foobar' -> `2/foobar'
$ ls -i1 */foobar
1053003 1/foobar
1053003 2/foobar

$ mkdir a; echo quux > a/foobar
$ mv 1 3; rsync -avPhyH --del --link-dest=../2 a/ 3
sending incremental file list
./
foobar
           5 100%    0.00kB/s    0:00:00 (xfer#1, to-check=0/2)

sent 105 bytes  received 34 bytes  278.00 bytes/sec
total size is 5  speedup is 0.04

$ ls -i1 */foobar
1053003 2/foobar
1053007 3/foobar
1053006 a/foobar

$ mv 2 4; rsync -avPhyH --del --link-dest=../3 a/ 4
sending incremental file list
./
foobar
           5 100%    0.00kB/s    0:00:00 (xfer#1, to-check=0/2)

sent 105 bytes  received 34 bytes  278.00 bytes/sec
total size is 5  speedup is 0.04


$ ls -il1 */foobar
1053007 -rw-r--r-- 1 math math 5 Mar 30 00:57 3/foobar
1053008 -rw-r--r-- 1 math math 5 Mar 30 00:57 4/foobar
1053006 -rw-r--r-- 1 math math 5 Mar 30 00:57 a/foobar

$ md5sum [34a]/foobar
d3b07a382ec010c01889250fce66fb13  3/foobar
d3b07a382ec010c01889250fce66fb13  4/foobar
d3b07a382ec010c01889250fce66fb13  a/foobar

Sekarang kami memiliki 2 cadangan a/foobaryang identik dalam semua hal, termasuk cap waktu, tetapi menempati berbagai inode.

Orang mungkin berpikir akan ada solusinya --delete-before, yang membunuh manfaat dari pemindaian bertahap tetapi ini tidak membantu karena file tidak akan dihapus, tetapi digunakan sebagai dasar jika salinan tambahan mungkin dilakukan.

Orang mungkin menduga lebih lanjut maka kita dapat mematikan lindung nilai tambahan-salin ini --whole-file, tetapi ini tidak membantu algoritma apa pun, tidak ada cara untuk mendapatkan apa yang kita inginkan.

Saya menganggap perilaku ini bug lain di rsync, di mana perilaku yang menguntungkan dapat ditafsirkan dari pemilihan yang cermat dari berbagai argumen perintah, tetapi hasil yang diinginkan tidak tersedia.

Sebuah solusi sayangnya akan bergerak dari rsync tunggal sebagai operasi atom ke dry-run dengan -n, logging itu, memproses log itu sebagai input untuk secara manual menghapus semua file yang diubah, kemudian menjalankan rsync --link-destuntuk mendapatkan apa yang kita inginkan - sebuah lumpur besar dibandingkan dengan rsync bersih tunggal.

Tambahan: mencoba melakukan pra-tautan $yesterdaydan $todaypada server cadangan sebelum pencadangan terhadap kotak produksi dengan rsync --link-dest=../$yesterday $yesterday/ $today- tetapi hasil yang sama - file apa pun yang ada dengan cara apa pun, bahkan 0 panjangnya, tidak akan pernah dihapus dan tautan-dihancurkan, sebagai gantinya keseluruhan salinan baru akan dibuat dari sumber dengan inode baru dan menggunakan lebih banyak ruang disk.

Melihat pax(1)sebagai solusi pra-tautan-sebelum-cadangan yang mungkin.

matematika
sumber
Saya menggunakan --delete-afterdalam skenario penggunaan ini, apa yang salah dengan ini?
gogoud
1
--delete-afterbaik-baik saja, tetapi tidak terkait dengan masalah yang dihadapi. File yang hilang dari sumber akan dihapus setelah salinan selesai. Masalah yang saya jelaskan berkaitan dengan cadangan yang dilakukan hari ini yang identik dengan kemarin tetapi terhadap file lama yang sudah ada yang tidak tertaut ke inode kemarin, tetapi disimpan sebagai file baru dua kali total ruang disk saat kemarin salinan identik dianggap.
matematika
Tidak sepenuhnya yakin apa pertanyaan Anda. Sudahkah Anda mempertimbangkan rsnapshot? Juga, pertimbangkan untuk menulis skrip kecil untuk menghubungkan kembali file "identik". Saya melakukan keduanya pada sistem saya.
roaima
1
Jika Anda tidak mendapatkan jawaban yang Anda butuhkan di sini, Anda dapat memposting di daftar rsync. Pengembang rsync secara teratur menjawab pertanyaan di sana bersama dengan banyak pengguna tingkat lanjut. Anda dapat menemukannya melalui lists.samba.org/mailman/listinfo/rsync . Saya kebanyakan bersembunyi di sana dan belajar banyak.
Joe
rsnapshot tidak akan mendaur ulang cadangan lama - dan saya perlu: jika saya memiliki cadangan 2 bulan dan 2-bulan + 1 hari, saya dapat menggilir satu sebagai target baru. Karena ~ 5% file berubah / hari, saya membuat 50K hardlink alih-alih 10 juta. Perbedaan kecepatan ini memungkinkan membuat cadangan 5 server / malam vs tidak. hardlink(1)lambat (15x lebih lambat dari pemindaian metadata rsync); paxlebih cepat tetapi meronta-ronta kepala HDD membandingkan cadangan lama dengan yang baru. rsync -nuntuk mendapatkan daftar delta berarti memukul server produksi dua kali (memindai 10 juta file jauh lebih berdampak daripada menyalin perubahan 50 ribu). Sakit mail daftar tentang opsi di rsync untuk memungkinkan ini.
matematika

Jawaban:

12

(Dikonversi dari edit pertanyaan)

Ini diselesaikan dengan memutakhirkan rsync. Versi 3.1.1 atau yang lebih baru sekarang akan mengganti file identik di target dan --link-destdirektori dengan satu file yang di-link. Menghemat banyak ruang.

Michael Mrozek
sumber