Anda dapat menggunakan --link-dest=
pilihan. Pada dasarnya Anda akan membuat folder baru, semua file ditautkan dengan keras ke yang baru. Setelah semuanya selesai, Anda tinggal menukar nama folder dan menghapus yang lama.
Tidak mungkin melakukan 100% atomik ini di Linux karena tidak ada dukungan kernel/VFS untuk itu. Namun, menukar nama sebenarnya hanya berjarak 2 syscall sehingga perlu waktu kurang dari 1 detik untuk menyelesaikannya. Ini hanya mungkin di Darwin (MAC/OSX) dengan panggilan sistem pertukaran data pada sistem file HFS.
Saya melakukan sesuatu yang mirip dengan rsync
backup [ke disk] dan saya mengalami masalah yang sama karena daemon memperbarui file saat pencadangan sedang berjalan.
Tidak seperti kebanyakan program, rsync memiliki banyak kode kesalahan yang berbeda [Lihat bagian bawah halaman manual]. Yang menarik adalah dua:
23 -- pengalihan sebagian karena kesalahan
24 -- transfer sebagian karena file sumber hilang
Ketika rsync melakukan transfer dan menemukan salah satu situasi ini, itu tidak berhenti begitu saja. Itu melompati dan melanjutkan dengan file yang bisa transfer. Pada akhirnya, ini menampilkan kode pengembalian.
Jadi, jika Anda mendapatkan kesalahan 23/24, jalankan kembali rsync. Proses selanjutnya akan jauh lebih cepat, biasanya hanya mentransfer file yang hilang dari proses sebelumnya. Pada akhirnya, Anda akan mendapatkan [atau seharusnya] hasil yang bersih.
Untuk menjadi atom, saya menggunakan dir "tmp" selama transfer. Kemudian, ketika rsync run sudah bersih, saya mengganti namanya [atomically] menjadi <date>
Saya juga menggunakan --link-dest
opsi, tetapi saya menggunakannya untuk menyimpan cadangan delta (mis. --link-dest=yesterday
untuk harian)
Meskipun saya belum menggunakannya sendiri, --partial-dir=DIR
dapat menjaga agar file tersembunyi tidak mengacaukan direktori cadangan. Pastikan bahwa DIR berada pada sistem file yang sama dengan direktori cadangan Anda sehingga penggantian nama akan bersifat atomik
Sementara saya melakukan ini di perl, saya menulis skrip yang merangkum apa yang telah saya katakan dengan sedikit lebih detail/presisi untuk situasi khusus Anda. Itu dalam sintaks mirip tcsh, [belum diuji dan agak kasar], tetapi perlakukan itu sebagai kode semu untuk menulis bash
Anda sendiri , perl
, python
skrip sesuai pilihan Anda. Perhatikan bahwa ini tidak membatasi percobaan ulang, tetapi Anda dapat menambahkannya dengan cukup mudah, sesuai keinginan Anda.
#!/bin/tcsh -f
# repo_backup -- backup repos even if they change
#
# use_tmp -- use temporary destination directory
# use_partial -- use partial directory
# use_delta -- make delta backup
# set remote server name ...
set remote_server="..."
# directory on server for backups
set backup_top="/path_to_backup_top"
set backup_backups="$backup_top/backups"
# set your rsync options ...
set rsync_opts=(...)
# keep partial files from cluttering backup
set server_partial=${remote_server}:$backup_top/partial
if ($use_partial) then
set rsync_opts=($rsync_opts --partial-dir=$server_partial)
endif
# do delta backups
if ($use_delta) then
set latest=(`ssh ${remote_server} ls $backup_backups | tail -1`)
# get latest
set delta_dir="$backup_backups/$latest"
if ($#latest > 0) then
set rsync_opts=($rsync_opts --link-dest=${remote_server}:$delta_dir)
endif
endif
while (1)
# get list of everything to backup
# set this to whatever you need
cd /local_top_directory
set transfer_list=(.)
# use whatever format you'd like
set date=`date +%Y%m%d_%H%M%S`
set server_tmp=${remote_server}:$backup_top/tmp
set server_final=${remote_server}:$backup_backups/$date
if ($use_tmp) then
set server_transfer=$server_tmp
else
set server_transfer=$server_final
endif
# do the transfer
rsync $rsync_opts $transfer_list $server_transfer
set code=$status
# run was clean
if ($code == 0) then
# atomically install backup
if ($use_tmp) then
ssh ${remote_server} mv $backup_top/tmp $backup_backups/$date
endif
break
endif
# partial -- some error
if ($code == 23) then
continue
endif
# partial -- some files disappeared
if ($code == 24) then
continue
endif
echo "fatal error ..."
exit(1)
end