2012-12-19 3 views
9

변수 이름이 $filename 인 파일에 무언가를 쓰고 싶습니다. 나는 그것을 덮어 쓰기를 원하지 않을, 그래서 존재하는 경우 먼저 확인하고 다음을 엽니 다Perl에 존재하지 않는 파일이 원자 열림

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

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

을하지만이 원자 없습니다. 이론적으로 누군가는 stage1stage2 사이에서이 파일을 만들 수 있습니다. 이 두 가지 일을 atomic 방식으로 수행하는 open 명령의 변형이 있습니까? 따라서 파일이 존재하면 쓰기 위해 파일을 열지 못합니다.

같은 파일을 수정 여러 Perl 스크립트 염려되는 경우

답변

4

, 당신이 관심있는 파일을 잠글 각 하나에 flock() 기능을 사용합니다.

외부 프로세스에 대한 걱정이 있다면 어떤 당신은 아마 제어 할 수 없어, 당신은 sysopen() 기능을 사용할 수 있습니다. (내가보기 엔 그건 그렇고, 추천)을 프로그래밍 펄 책에 따르면 :

덮어 쓰기의이 문제를 해결하려면, 당신은 이 작성 여부를 통해 개별 컨트롤을 제공하는 sysopen를 사용해야합니다 새 파일 또는 기존 파일을 덮어 씁니다. 그리고 우리는 –e 파일 존재 테스트 을 여기에서 유용 할 목적으로 제공하지 않으며 단지 을 경합 조건으로 만 증가시키기 때문에 우리는 도랑을 파냅니다.

그들은 또한이 코드 샘플 블록 제공가 처음 몇 상수 당겨,이 예에서는

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 통화에 사용되는). 그런 다음 파일을 열려고 시도하면 open이 표시되고 실패하면 sysopen이 표시됩니다. 그들은 말을 계속 :

이제 파일이 어떻게 든 열려 이 실패하고 sysopen 시도 쓰기에 대한 새 파일을 열 때 플래그를 제공과 함께 있기 때문에, 전혀 해를 끼치 지 가 완료되지 않은 경우 사이에 존재로 온천 경우에도, sysopen은 이미 존재하는 파일 을 열지 않습니다.

따라서, 상황에 맞는 일을 명확하게하기 위해 완전히 (더 이상 단계 1) 파일 테스트를 제거하고, 위의 블록과 유사한 코드를 사용하여 열기 작업을한다. 문제 해결됨!

+0

이 여전히 해결되지 않는 * 이론적으로 누군가가 스테이지 1과 스테이지 2 * 문제 사이에이 파일을 만들 수 있습니다! 그것은 단지 파일을 여는 비 충돌 방식입니다. – creaktive

+0

물론 있습니다. 우리는 OP 질문에서 "1 단계"를 완전히 없앴습니다. 이제 단 하나의 스테이지 만 있습니다 : 파일 열기! –

+0

의견에 동의하지 않아서 ... 'open (FH, "<", $ file) || (! 1 자) || sysopen (...)'? 여전히 두 단계가 있습니다. 여러분은 그것들을 같은 문장에 넣기 만하면됩니다.내가 틀렸다면 나를 바로 잡아주세요. – creaktive

6

다음은 파일 열기의 원자 방법 :

#!/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; 

디버그 세션 :

[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

무리가 필요한 경우 OP의 질문에 대답하지 않습니다. 필요합니까, 아니면 sysopen가 트릭을합니까? – ikegami

+0

@ikegami 고맙습니다. flock()이 비슷한 코드에 있지만 질문과 관련이 없다는 답변을 편집했습니다. – creaktive

관련 문제