9

名前が変数にあるファイルに何かを書きたいのですが$filename。上書きしたくないので、まず存在するかどうかを確認してから開きます。

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

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

しかし、これはアトミックではありません。stage1理論的には、誰かがとの間でこのファイルを作成できますstage2。これらの両方をアトミックな方法で実行するコマンドのバリアントがいくつかあるopenので、ファイルが存在する場合、書き込み用にファイルを開くことができませんか?

4

2 に答える 2

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;

デバッグ セッション:

stas@Stanislaws-MacBook-Pro:~/stackoverflow$ cat test
Wed Dec 19 12:10:37 2012
stas@Stanislaws-MacBook-Pro:~/stackoverflow$ perl sysopen.pl 
file test exists, not overwriting
stas@Stanislaws-MacBook-Pro:~/stackoverflow$ cat test
Wed Dec 19 12:10:37 2012
于 2012-12-19T14:13:52.717 に答える
3

複数の Perl スクリプトが同じファイルを変更することに懸念がある場合は、それぞれのスクリプトでflock()関数を使用して、関心のあるファイルをロックしてください。

おそらく制御できない外部プロセスが心配な場合は、sysopen()関数を使用できます。Programming Perlの本によると(ちなみに、これを強くお勧めします):

この上書きの問題を解決するには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ます。彼らは続けてこう言います:

sysopenopen が失敗してから書き込み用に新しいファイルを開こうとするまでの間にファイルが何らかの形で存在するようになったとしても、提供されたフラグsysopenを使用すると、既に存在するファイルを開くことを拒否するため、害はありません。

そのため、状況を明確にするために、ファイル テストを完全に削除し (ステージ 1 を削除)、上記のブロックと同様のコードを使用して開く操作のみを実行します。問題が解決しました!

于 2012-12-19T14:05:46.900 に答える