Apache bir tür dosyayı tek bir yere yazıyorsa ve yazmayı tamamlamamışsa versync
içeri giriyorsa, rsync
orada oturan her şeyi kopyalar.
Yani Apache 5MB'lık bir dosyayla uğraşıyorsa, sadece 2MB yazılır ve başlarsa, 2MB'lık rsync
kısmi dosya kopyalanacaktır. Yani bu dosya hedef sunucuda “bozuk” gibi görünüyor.
Kullandığınız dosyaların boyutuna bağlı olarak , aşağıdakileri yapmak için --inplace
seçeneğini kullanabilirsiniz rsync
:
Bu seçenek, dosyanın verileri güncellenmesi gerektiğinde rsync'in bir dosyayı nasıl aktardığını değiştirir: dosyanın yeni bir kopyasını oluşturmak ve tamamlandığında yerine taşımak için varsayılan yöntem yerine, rsync güncellenmiş verileri doğrudan hedefe yazar dosya.
Bunun yararı, bir 5MB dosyasında yalnızca ilk çalıştırmada 2MB kopyalanmış olması durumunda, bir sonraki çalıştırma 2MB'de toplanacak ve tam 5MB yerinde olana kadar dosyayı kopyalamaya devam edecektir.
Olumsuz tarafı, bir dosya kopyalanırken birisinin web sunucusuna eriştiği ve sonra kısmi bir dosya göreceği bir durum oluşturabilmesidir. Bence rsync
en iyi sonucu, "görünmez" bir dosyayı önbelleğe alma ve hemen yerine taşıma varsayılan davranışı. Ancak --inplace
büyük dosyaların ve bant genişliği kısıtlamalarının büyük bir dosyanın kareden birinden kolayca kopyalanmasının önüne geçebileceği senaryolar için iyidir.
Bunu söylediğini söyledi; vurgu benimdir:
Her beş dakikada bir cron run rsync var…
Bu cron işini yönetmek için bazı bash betiğiniz olduğunu varsayalım? Şey, rsync
sadece kopyalanması gereken dosyaları kopyalamak için yeterince akıllı. Ve her 5 dakikada bir çalışan bir komut dosyanız rsync
varsa, daha hızlı giderse birbirinize adım atmaktan kaçınmaya çalışıyorsunuz . Yani, her dakika rsync
çalıştırırsanız, dosya boyutu veya ağ hızı nedeniyle bir veya daha fazla işlemin devam etme riski vardır ve bir sonraki işlem sadece onunla rekabet edebilir; bir yarış koşulu.
Bundan kaçınmanın bir yolu, tüm rsync
komutunuzu bir dosya kilidini kontrol eden bir bash betiğine sarmaktır; Aşağıda böyle durumlar için kullandığım bir boilerplate bash script çerçevesi var.
Bazı kişilerin kullanmanızı flock
önereceğim flock
, ancak kullandığım bazı sistemlerde yüklü olmadığından ve Ubuntu (sahip olduğu) ve Mac OS X (ki olmayan) arasında atladığımı unutmayın - bu basit çerçeveyi gerçek bir sorun olmadan kullanıyorum:
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
Fikir, genel çekirdeğin echo "Hello world!"
- sahip olduğum yerde - senaryonuzun kalbinin nerede olduğu. Geri kalanı temel olarak bir kilitleme mekanizması / mantığıdır mkdir
. Kavramın iyi bir açıklaması bu cevapta :
mkdir henüz yoksa bir dizin oluşturur ve varsa bir çıkış kodu ayarlar. Daha da önemlisi, tüm bunları tek bir atomik eylemde yapar ve bu senaryo için mükemmel hale getirir.
Bu nedenle, rsync
işleminiz için, sadece echo
komutunuzu komutunuza değiştirerek bu komut dosyasını kullanmanızı tavsiye ederim rsync
. Ayrıca, LOCK_NAME
gibi bir şey değiştirin RSYNC_PROCESS
ve sonra gitmek için iyidir.
Şimdi rsync
bu komut dosyasına sarıldığınızda, iki veya daha fazla rsync
işlemin aynı şeyi yapmak için savaştığı bir yarış koşulu riski olmadan her dakika çalışacak şekilde cron işini ayarlayabilirsiniz . Bu, rsync
aktarılan kısmi dosyalar sorununu ortadan kaldırmayacak hızı veya güncellemeleri artırmanıza izin verecektir , ancak tüm dosyanın bir noktada düzgün bir şekilde kopyalanabilmesi için genel işlemin hızlanmasına yardımcı olacaktır.