Jika Apache menulis semacam file ke satu tempat dan belum selesai menulisnya lalu rsync
masuk, rsync
akan menyalin apa pun yang ada di sana.
Artinya jika Apache berurusan dengan file 5MB, hanya 2MB yang ditulis dan rsync
masuk, file 2MB parsial akan disalin. Sehingga file tersebut seolah-olah “rusak” di server tujuan.
Bergantung pada ukuran file yang Anda gunakan, Anda dapat menggunakan --inplace
opsi di rsync
untuk melakukan hal berikut:
Opsi ini mengubah cara rsync mentransfer file saat data file perlu diperbarui:alih-alih metode default untuk membuat salinan baru file dan memindahkannya ke tempatnya saat selesai, rsync malah menulis data yang diperbarui langsung ke file tujuan.
Keuntungan dari ini adalah jika file 5MB hanya memiliki 2MB yang disalin pada proses pertama, proses berikutnya akan mengambil 2MB dan terus menyalin file hingga 5MB penuh tersedia.
Negatifnya adalah hal itu dapat menciptakan situasi di mana seseorang mengakses server web saat file sedang disalin dan kemudian mereka akan melihat sebagian file. Menurut saya rsync
berfungsi paling baik dalam perilaku defaultnya untuk menyimpan file "tidak terlihat" dan kemudian segera memindahkannya ke tempatnya. Tapi --inplace
bagus untuk skenario di mana file besar dan batasan bandwidth mungkin menghalangi file besar yang mudah disalin dari awal.
Yang mengatakan Anda menyatakan ini; penekanan adalah milikku:
Setiap lima menit telah menjalankan cron rsync…
Jadi saya berasumsi Anda memiliki beberapa skrip bash untuk mengelola tugas cron ini? Nah, masalahnya adalah rsync
cukup pintar untuk hanya menyalin file yang perlu disalin. Dan jika Anda memiliki skrip yang berjalan setiap 5 menit, tampaknya Anda mencoba menghindari rsync
menginjak satu sama lain jika berjalan lebih cepat. Artinya, jika Anda menjalankannya setiap menit, ada risiko salah satu atau lebih dari rsync
proses akan tetap berjalan karena ukuran file atau kecepatan jaringan dan proses selanjutnya hanya akan bersaing dengannya; kondisi balapan.
Salah satu cara untuk menghindarinya adalah dengan membungkus seluruh rsync
Anda perintah dalam skrip bash yang memeriksa kunci file; di bawah ini adalah framework skrip bash boilerplate yang saya gunakan untuk kasus seperti ini.
Perhatikan bahwa beberapa orang akan merekomendasikan penggunaan flock
tapi sejak flock
tidak diinstal pada beberapa sistem yang saya gunakan—dan saya beralih antara Ubuntu (yang memilikinya) dan Mac OS X (yang tidak) banyak—Saya menggunakan kerangka kerja sederhana ini tanpa masalah nyata:
LOCK_NAME="MY_GREAT_BASH_SCRIPT"
LOCK_DIR='/tmp/'${LOCK_NAME}.lock
PID_FILE=${LOCK_DIR}'/'${LOCK_NAME}'.pid'
if mkdir ${LOCK_DIR} 2>/dev/null; then
# If the ${LOCK_DIR} doesn't exist, then start working & store the ${PID_FILE}
echo $$ > ${PID_FILE}
echo "Hello world!"
rm -rf ${LOCK_DIR}
exit
else
if [ -f ${PID_FILE} ] && kill -0 $(cat ${PID_FILE}) 2>/dev/null; then
# Confirm that the process file exists & a process
# with that PID is truly running.
echo "Running [PID "$(cat ${PID_FILE})"]" >&2
exit
else
# If the process is not running, yet there is a PID file--like in the case
# of a crash or sudden reboot--then get rid of the ${LOCK_DIR}
rm -rf ${LOCK_DIR}
exit
fi
fi
Idenya adalah inti umum itu—di mana saya memiliki echo "Hello world!"
—Adalah inti dari naskah Anda. Sisanya pada dasarnya adalah mekanisme/logika penguncian berdasarkan mkdir
. Penjelasan konsep yang bagus ada di jawaban ini:
mkdir membuat direktori jika belum ada, dan jika ya, itu menetapkan kode keluar. Lebih penting lagi, semua ini dilakukan dalam aksi atom tunggal sehingga sempurna untuk skenario ini.
Jadi dalam kasus rsync
Anda proses, saya akan merekomendasikan menggunakan script ini dengan hanya mengubah echo
perintah ke rsync
Anda memerintah. Juga, ubah LOCK_NAME
ke sesuatu seperti RSYNC_PROCESS
dan kemudian Anda baik untuk pergi.
Sekarang dengan rsync
Anda dibungkus dengan skrip ini, Anda dapat mengatur tugas cron untuk berjalan setiap menit tanpa risiko kondisi balap di mana dua atau lebih rsync
proses berjuang untuk melakukan hal yang sama. Ini akan memungkinkan Anda untuk meningkatkan kecepatan atau rsync
pembaruan yang tidak akan menghilangkan masalah transfer sebagian file, tetapi ini akan membantu mempercepat keseluruhan proses sehingga file lengkap dapat disalin dengan benar di beberapa titik.
Ya - dan file mungkin rusak jika rsync membaca file pada saat yang sama saat file sedang ditulis.
Anda dapat mencoba ini:https://unix.stackexchange.com/a/2558
Anda juga dapat membuat skrip dengan lsof:
lsof /path/to file
Kode keluar 0 berarti file sedang digunakan, dan kode keluar 1 berarti tidak ada aktivitas pada file tersebut.