2012-12-19 14 views
9

$filename değişkeninde bir dosyaya bir şeyler yazmak istiyorum. Bunu üzerine yazmak istemiyorum, bu yüzden varsa ilk kontrol ve sonra açın:Perl'de mevcut olmayan dosyanın atomik açıklığı

#stage1 
if(-e $filename) 
{ 
    print "file $filename exists, not overwriting\n"; 
    exit 1; 
} 

#stage2 
open(OUTFILE, ">", $filename) or die $!; 

Ama bu atom değildir. Teorik olarak birisi bu dosyayı stage1 ve stage2 arasında oluşturabilir. Her iki şeyi de atomik şekilde yapacak open komutunun bir varyantı var mı, bu yüzden dosya varsa, bir dosya açmak için başarısız olur?

Aynı dosyasında değişiklik birden Perl komut konusunda endişeleriniz varsa

cevap

4

, sadece ilgilendiğiniz dosyayı kilitlemek için her birinde flock() işlevini kullanın.

harici süreçler hakkında endişeleniyorsanız hangi Muhtemelen kontrolünüz yok, sysopen() işlevini kullanabilirsiniz. (Çok arada, tavsiye) Programlama Perl Kitaba göre:

üzerine yazarak bu sorunu çözmek için, bir oluşturmak isteyip üzerinde tek denetimleri sağlayan, sysopen kullanmanız gerekir Yeni dosya veya varolan bir tane. Ve burada –e dosya varlığı testini geçersiz kılmaya çalışacağız, çünkü burada yararlı bir amaca hizmet etmiyor ve sadece pozlama koşullarımızı yarış koşullarına arttırıyoruz.

Ayrıca kod örnek bloğu sağlar: ilk birkaç sabitleri çekme, bu örnekte

use Fcntl qw/O_WRONLY O_CREAT O_EXCL/; 
open(FH, "<", $file) 
    || sysopen(FH, $file, O_WRONLY | O_CREAT | O_EXCL) 
    || die "can't create new file $file: $!"; 

(sysopen çağrı kullanılmak üzere). Ardından, dosyayı open ile açmaya çalışırlar ve bu başarısız olursa, sysopen'u dener. Şöyle devam devam:

Şimdi dosya nasılsa açık başarısız olur ve sysopen çalışır yazma için yeni bir dosya açmak için zaman bayraklar sağlanan ile çünkü hiçbir zarar , bittiğinde arasındaki varlık haline yaylar bile, sysopen, zaten var olan bir dosyayı açmayı reddeder.

Yani, durumunuza şeyleri açıklığa kavuşturmak için tamamen (artık sahne 1) dosyası testini kaldırmak ve sadece yukarıdaki bloğuna benzer bir kod kullanarak açık operasyon yapmak. Sorun çözüldü!

+0

Bu hala çözmez * Teorik birisi stage1 ve stage2 * sorunu arasındaki bu dosya oluşturabilirsiniz! Dosyaları açmanın sadece bir karalama şekli değil. – creaktive

+0

Elbette öyle. OP'nin sorusundan tamamen "aşama 1" ten kurtulduk. Şimdi sadece bir aşama var: dosyanın açılması! –

+0

Katıldığım için üzgünüm ... Açık olan (FH, "<", $ dosya) || || (! uyku 1) || sysopen (...) '? Hala iki aşama var, onları aynı ifadeye koydun.Yanılıyorsam lütfen beni düzeltin. – creaktive

6

İşte açılış dosyalarının bir atom yoludur:

#!/usr/bin/env perl 
use strict; 
use warnings qw(all); 

use Fcntl qw(:DEFAULT :flock); 

my $filename = 'test'; 
my $fh; 

# this is "atomic open" part 
unless (sysopen($fh, $filename, O_CREAT | O_EXCL | O_WRONLY)) { 
    print "file $filename exists, not overwriting\n"; 
    exit 1; 
} 

# flock() isn't required for "atomic open" per se 
# but useful in real world usage like log appending 
flock($fh, LOCK_EX); 

# use the handle as you wish 
print $fh scalar localtime; 
print $fh "\n"; 

# unlock & close 
flock($fh, LOCK_UN); 
close $fh; 

ayıklama oturumu:

[email protected]:~/stackoverflow$ cat test 
Wed Dec 19 12:10:37 2012 
[email protected]:~/stackoverflow$ perl sysopen.pl 
file test exists, not overwriting 
[email protected]:~/stackoverflow$ cat test 
Wed Dec 19 12:10:37 2012 
+1

Eğer sürü gerekli ise, bu OP'nin sorusuna cevap vermiyor. Gerekli mi, yoksa sysopen hile mi yapıyor? – ikegami

+0

Teşekkür ederim @ikegami, ben 'flock()' genel olarak benzer kodda mevcut olsa da, soruyla ilgili olmadığını işaret etmek için cevabı düzenledim. – creaktive

İlgili konular