NFS'yi sordunuz. Bu tür kodun NFS altında kırılması muhtemeldir, çünkü denetim noclobber
iki ayrı NFS işlemi içerdiğinden (dosyanın var olup olmadığını kontrol edin, yeni dosya oluştur) ve iki ayrı NFS istemcisinden iki işlem her ikisinin de başarılı olduğu bir yarış durumuna girebilir ( her ikisi de B.part
henüz var olmadığını doğrular , ardından her ikisi de başarılı bir şekilde oluşturmaya devam eder, sonuç olarak birbirlerinin üzerine yazarlar.)
Yazdığınız dosya sisteminin noclobber
atom gibi bir şeyi destekleyip desteklemeyeceği konusunda genel bir denetim yapmanız gerekmez. Dosya sistemi türünü NFS olup olmadığını kontrol edebilirsiniz, ancak sezgisel ve mutlaka bir garanti değildir. SMB / CIFS (Samba) gibi dosya sistemlerinin aynı sorunlardan muzdarip olması muhtemeldir. FUSE yoluyla ortaya çıkan dosya sistemleri doğru davranabilir veya davranmayabilir, ancak bu çoğunlukla uygulamaya bağlıdır.
Muhtemelen daha iyi bir yaklaşım, B.part
benzersiz bir dosya adı kullanarak (diğer ajanlarla işbirliği yoluyla) adımda çarpışmayı önlemek, böylece güvenmenize gerek kalmaz noclobber
. Örneğin, dosya adının bir parçası olarak ana bilgisayar adınızı, PID'nizi ve bir zaman damgasını (+ muhtemelen rastgele bir sayı) dahil edebilirsiniz. Belirli bir PID altında belirli bir PID altında herhangi bir zamanda çalışan tek bir işlem olması gerektiğinden, bu benzersizliği garanti eder.
Yani şunlardan biri:
test -f B && continue # skip already existing
unique=$(hostname).$$.$(date +%s).$RANDOM
cp A B.part."$unique"
# Maybe check for existance of B again, remove
# the temporary file and bail out in that case.
mv B.part."$unique" B
# mv (rename) should always succeed, overwrite a
# previously copied B if one exists.
Veya:
test -f B && continue # skip already existing
unique=$(hostname).$$.$(date +%s).$RANDOM
cp A B.part."$unique"
if ln B.part."$unique" B ; then
echo "Success creating B"
else
echo "Failed creating B, already existed"
fi
# Both cases require cleanup.
rm B.part."$unique"
Dolayısıyla, iki ajan arasında bir yarış durumunuz varsa, her ikisi de işleme devam eder, ancak son işlem atomik olacaktır, bu nedenle B, A'nın tam bir kopyasıyla veya B mevcut değildir.
Kopyadan sonra ve mv
veya ln
operasyondan önce tekrar kontrol ederek yarışın boyutunu azaltabilirsiniz , ancak hala küçük bir yarış durumu var. Ancak, yarış koşuluna bakılmaksızın, her iki işlemin de A'dan (veya kaynak olarak geçerli bir dosyadan bir kopya) oluşturmaya çalıştığı varsayılarak, B'nin içeriği tutarlı olmalıdır.
İlk durumda mv
, bir yarış olduğunda, son işlem kazanan işlemdir, çünkü rename (2) mevcut bir dosyayı atomik olarak değiştirecektir:
Eğer NEWPATH zaten var erişim girişiminde başka süreç hangi anlamı yok ki, bu atomik değiştirilecektir NEWPATH eksik bulacaksınız. [...]
Eğer NEWPATH var ama operasyon nedense başarısız, rename()
garanti bir örneğini bırakmak NEWPATH yerinde.
Bu nedenle, o zaman B tüketen işlemlerin bu işlem sırasında farklı sürümlerini (farklı inode) görebilir. Yazarlar sadece aynı içeriği kopyalamaya çalışıyorsa ve okuyucular sadece dosyanın içeriğini tüketiyorsa, bu iyi olabilir, aynı içeriğe sahip dosyalar için farklı kodlar alırlarsa, aynı şekilde mutlu olurlar.
Sabit bir bağlantı kullanan ikinci yaklaşım daha iyi görünüyor , ancak birçok eşzamanlı istemciden NFS'de sıkı bir döngüde hardlinklerle deneyler yapmayı ve başarıyı saymayı hatırlıyorum ve hala iki istemci bir hardlink yayınladığında göründüğü bazı yarış koşulları var gibi görünüyor operasyon aynı anda, aynı hedefle, her ikisi de başarılı görünüyordu. (Bu davranışın belirli NFS sunucusu uygulaması YMMV ile ilgili olması mümkündür.) Her durumda, muhtemelen aynı tür bir yarış durumu, burada ağır olduğu durumlarda aynı dosya için iki ayrı inode elde edebilirsiniz. bu yarış koşullarını tetiklemek için yazarlar arasındaki uyumluluk. Yazarlarınız tutarlıysa (her ikisi de A'dan B'ye kopyalanıyorsa) ve okuyucularınız yalnızca içeriği tüketiyorsa, bu yeterli olabilir.
Sonunda kilitlemeden bahsettin. Maalesef kilitleme en azından NFSv3'te ciddi bir şekilde eksik (NFSv4 hakkında emin değilim, ama ben de iyi değil.) Kilitlemeyi düşünüyorsanız, dağıtılmış kilitleme için farklı protokollere bakmalısınız, muhtemelen bantla gerçek dosya kopyaları, ama bu hem yıkıcı, karmaşık ve çıkmaz gibi sorunlara yatkın, bu yüzden kaçınılması daha iyi olduğunu söyleyebilirim.
NFS'de atomiklik konusunda daha fazla arka plan için, kilitleri önlemek ve NFS'de bile güvenilir bir şekilde çalışmak için oluşturulan Maildir posta kutusu biçimini okumak isteyebilirsiniz . Bunu benzersiz dosya adlarını her yerde tutarak yapar (böylece sonunda nihai bir B bile elde edemezsiniz.)
Belki de sizin durumunuz için biraz daha ilginç olan Maildir ++ formatı Maildir'i posta kutusu kotasına destek eklemek için genişletir ve bunu posta kutusunun içinde sabit bir ada sahip bir dosyayı atomik olarak güncelleyerek yapar (böylece B'nize daha yakın olabilir) NFS'de gerçekten güvenli değil, ancak buna benzer bir prosedür kullanan ve atomik bir değişim olarak geçerli olan bir yeniden hesaplama yaklaşımı var.
Umarım tüm bu işaretçiler faydalı olacaktır!