Perilaku rsync dengan file yang masih ditulis?

12

Jika Apache sedang menulis file besar dan tugas cs rsync berjalan pada file itu, apakah rsync berusaha menyalin file?

Contoh

  • Apache-1: Memiliki file besar yang sedang ditulis /var/www.
  • Apache-2: Klon dari Apache-1. Setiap lima menit memiliki cron run rsync untuk mendapatkan /var/wwwsinkronisasi.
Louis Waweru
sumber

Jawaban:

20

Jika Apache sedang menulis file dari satu jenis ke satu tempat dan belum selesai menulisnya lalu rsync menendang, rsyncakan menyalin apa pun yang ada di sana.

Berarti jika Apache berurusan dengan file 5MB, hanya 2MB yang ditulis dan rsyncdimulai, file 2MB parsial akan disalin. Jadi file itu akan tampak seperti "rusak" di server tujuan.

Bergantung pada ukuran file yang Anda gunakan, Anda dapat menggunakan --inplaceopsi rsyncuntuk melakukan hal berikut:

Opsi ini mengubah cara rsync mentransfer file ketika data file perlu diperbarui: alih-alih metode default untuk membuat salinan file baru dan memindahkannya ke tempatnya ketika selesai, rsync sebagai gantinya menulis data yang diperbarui langsung ke tujuan mengajukan.

Manfaatnya adalah jika file 5MB hanya memiliki 2MB yang disalin pada proses pertama, proses berikutnya akan mengambil pada 2MB dan terus menyalin file hingga 5MB penuh di tempat.

Yang negatif adalah bahwa hal itu dapat menciptakan situasi di mana seseorang mengakses server web saat file sedang disalin dan kemudian mereka akan melihat sebagian file. Menurut pendapat saya rsyncbekerja paling baik di dalamnya perilaku default caching file "tidak terlihat" dan kemudian memindahkannya ke tempatnya segera. Tetapi --inplacebagus untuk skenario di mana file besar dan batasan bandwidth mungkin menghalangi file besar yang mudah disalin dari persegi.

Yang mengatakan Anda menyatakan ini; penekanan adalah milikku:

Setiap lima menit memiliki cron run rsync…

Jadi saya menganggap Anda memiliki beberapa skrip bash untuk mengelola pekerjaan cron ini? Nah, masalahnya rsynccukup pintar untuk hanya menyalin file yang perlu disalin. Dan jika Anda memiliki skrip yang berjalan setiap 5 menit tampaknya Anda mencoba untuk menghindari saling rsyncmenginjak jika berjalan lebih cepat. Artinya, jika Anda menjalankannya setiap menit, ada risiko bahwa satu atau lebih rsyncproses masih akan berjalan karena ukuran file atau kecepatan jaringan dan proses selanjutnya hanya akan bersaing dengannya; kondisi balap.

Salah satu cara untuk menghindari ini adalah dengan membungkus seluruh rsyncperintah Anda dalam skrip bash yang memeriksa kunci file; di bawah ini adalah kerangka skrip bash boilerplate yang saya gunakan untuk kasus-kasus seperti ini.

Perhatikan bahwa beberapa orang akan merekomendasikan penggunaan flocktetapi karena flocktidak diinstal pada beberapa sistem yang saya gunakan — dan saya beralih di 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 — di mana saya memiliki echo "Hello world!"— adalah tempat inti naskah Anda. Sisanya pada dasarnya adalah mekanisme penguncian / logika berdasarkan mkdir. Penjelasan konsep yang baik ada dalam jawaban ini :

mkdir membuat direktori jika belum ada, dan jika ada, ia menetapkan kode keluar. Lebih penting lagi, ia melakukan semua ini dalam aksi atom tunggal sehingga sempurna untuk skenario ini.

Jadi dalam hal rsyncproses Anda , saya akan merekomendasikan menggunakan skrip ini dengan hanya mengubah echoperintah ke rsyncperintah Anda . Juga, ubah LOCK_NAMEke sesuatu seperti RSYNC_PROCESSdan kemudian Anda baik untuk pergi.

Sekarang dengan rsyncdibungkus dengan skrip ini, Anda dapat mengatur tugas cron untuk berjalan setiap menit tanpa risiko kondisi balapan di mana dua atau lebih rsyncproses berjuang untuk melakukan hal yang sama. Ini akan memungkinkan Anda untuk meningkatkan kecepatan atau rsyncpembaruan yang tidak akan menghilangkan masalah file parsial yang ditransfer, tetapi ini akan membantu mempercepat proses keseluruhan sehingga file lengkap dapat disalin dengan benar di beberapa titik.

JakeGould
sumber
1
Terima kasih telah menunjukkan kemungkinan beberapa rsyncs berjalan, tidak memikirkan itu. Naskahnya terdengar bagus. Saya hanya mencoba memahami cara menyinkronkan situs yang seimbang dengan rsync, dan ini sepertinya meringankan mereka. Bonus luar biasa. Masih merasa mungkin ini pendekatan yang salah ... tapi mari kita lihat :)
Louis Waweru
@Louis Sama-sama! Juga, jika Anda ingin menjaga folder tetap sinkron berdasarkan perubahan file langsung, saya akan sangat menyarankan untuk menggunakan / mengadaptasi lsyncd. Ini memungkinkan Anda untuk memiliki "folder panas" yang benar-benar memperhatikan aktivitas di dalamnya dan kemudian bertindak pada file-file tersebut ketika perubahan dibuat. Saya menggunakan rsyncbanyak hal seperti yang dijabarkan dalam jawaban saya, tetapi saya gunakan lsyncduntuk kasus-kasus yang membutuhkan bentuk tindakan non-cron / lebih cepat.
JakeGould
3

Ya - dan file mungkin rusak jika rsync membaca file pada saat yang sama file sedang ditulis.

Anda dapat mencoba ini: /unix//a/2558

Anda juga dapat membuat skrip dengan lsof:

lsof /path/to file

Kode keluar 0 berarti bahwa file sedang digunakan, dan kode keluar 1 berarti tidak ada aktivitas pada file itu.

pemberontak
sumber
Saya tidak melihat mengapa file tersebut akan rusak jika rsync hanya membacanya
puas