【perlメモ】flockの使い方
flockはファイルの排他制御を行ってファイルが同時に書き込みアクセスされることによって破損するのを防ぐのに利用する関数です。割とよく使うのですが、一連の処理が割とうろ覚えになるのでメモっておきます。
flockを利用した一連の処理の流れとしては下のような感じ。
- ファイルのopen
- flockで排他制御
- seekでファイルのシーク位置をファイルの先頭に移動
- ファイルに書き込み
- truncateでファイルのサイズを変更。tellは現在のファイル位置(つまり現在のファイルサイズ)を返す。
- ファイルのclose
flock(FILE,8)でファイルのロックを解除しないのはcloseすると自動で解除されるからです。flock(FILE,8)で解除してからcloseすると、ファイルをcloseする前に排他制御が解除されて隙が生まれるため、flock(FILE,8)とclose(FILE)の間に他のアクセスがあった場合ファイルが破損する可能性が出てくるためclose(FILE)で自動で解除してもらうほうがファイルの破損の可能性が低くなります。
sample.pl
#!/usr/bin/perl
use strict;
use warnings;
open(FILE,"test.txt") || die $!;
flock(FILE,2);
seek(FILE,0,0);
print FILE "abcdefg\n";
truncate(FILE,tell(FILE));
close(FILE);
ちょっとデバッグログを出力したい時の為の簡単なサンプル。(最大1000行までデバッグログを保存するという仕様の場合。)
Windows上のperlで利用するのを前提に最後の行はcp932になっているが、他の文字コードで標準出力したい場合は他の文字コードを指定すればOK。デバッグログにはutf-8で出力。モジュールを使うまでもないちょっとしたデバッグ時に使っている。
sample2.pl(utf-8)
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
my $dbglog = ‘deblog.txt’;
#デバッグログファイルが無いときは作る
unless( -e "$dbglog"){
open(FILE,">$dbglog") || die $!;
close(FLIE);
}
&debug_print("abcdefg\n");
#====================================================================
# &debug_print( str );
#====================================================================
sub debug_print{
open(FILE,"+<:utf8","$dbglog") || die $!;
flock(FILE,2);
my $str = decode_utf8($_[0]);
my @dbglog = <FILE>;
push(@dbglog,$str);
while(scalar(@dbglog) > 1000){
shift(@dbglog);
}
seek(FILE,0,0);
foreach(@dbglog){
print FILE $_;
}
truncate(FILE,tell(FILE));
close(FILE);
print encode(‘cp932’,$str);
}