【Perl】ファイルロック(排他処理)について語ろう
■ このスレッドは過去ログ倉庫に格納されています
0001nobodyさん
02/06/23 10:18ID:eY2l+Gw10382nobodyさん
03/05/22 13:53ID:???ttp://homepage1.nifty.com/glass/tom_neko/web/web_04.html
このへんでも参考に
0383380 じゃないけど
03/05/22 15:06ID:???激しく参考になりますた。謝謝。
ところで
flock() が使えないところで
eval{ if(!(flock(FH, 2))){ &function; } };
とした場合ちゃんとサブルチンに逝ってくれますか?
false は返ってくるんでしょうか?
0384nobodyさん
03/05/22 15:40ID:Mzhw6+0oサンクスコ(・∀・)
0385nobodyさん
03/05/23 13:24ID:ORCLTuvqアンロックする時にrmdirでディレクトリ削除ってことですよね?
>>382のサイト見てないけど…。
0387山崎渉
03/05/28 17:07ID:???ピュ.ー ( ^^ ) <これからも僕を応援して下さいね(^^)。
=〔~∪ ̄ ̄〕
= ◎――◎ 山崎渉
0388nobodyさん
03/05/28 18:03ID:???0389nobodyさん
03/05/31 21:04ID:n0OtuFEQ他のプロセスでロックしてるファイルにアクセスしてもロックがすぐ終っちゃうような…。
どうすれバインダー。
0390動画直リン
03/05/31 21:10ID:1EAhrEiJ0392389
03/05/31 21:45ID:n0OtuFEQ0393nobodyさん
03/05/31 22:08ID:nC5SP5sDロック中に
sleep 60;
0394nobodyさん
03/05/31 23:30ID:???package FileLock;
use IO::File;
my $CAT= '/bin/cat';
sub open_w {
my $filename= shift;
mkdir($filename)unless -d $filename;
my $base= sprintf("%s.%s.",time,$$);
my $cnt= 0;
$cnt++ while(-f "$filename/$base$cnt");
return IO::File->new("$filename/$base$cnt",'>>');
}
sub open_r {
my $filename= shift;
return IO::File->new("|$CAT $filename/*");
}
1;
0395nobodyさん
03/06/01 04:57ID:Hll/ZLYfおぉ!蟻がとう。
0398nobodyさん
03/06/01 21:54ID:???flockと組み合わせて(かつcron回してファイルをまとめつつ)
使ってたんだけど。。。駄目かぁ(´Д`;)
0399nobodyさん
03/06/02 00:36ID:???> mkdir($filename)unless -d $filename;
意味なし。複数のプロセスでunless -d $filenameが成立する可能性がある。
排他制御するにはアトミックにやらないと駄目。
排他制御に強い/弱いは無い。正しいか駄目のどちらか一方、わずかでも可能性があれば駄目ロック。
0400nobodyさん
03/06/02 09:59ID:7y9vki3n--$retry <= 0
なんてやってるの?
$retry--
じゃまずいの?
0401nobodyさん
03/06/02 10:09ID:Ixodm31chttp://www1.free-city.net/home/s-rf9/page006.html
0402nobodyさん
03/06/02 10:20ID:sw1UrgM5( ´∀`)/< 先生もろDVDはどこですか?
_ / / / \___________
\⊂ノ ̄ ̄ ̄ ̄\
||\ \
||\|| ̄ ̄ ̄ ̄ ̄||
|| || ̄ ̄ ̄ ̄ ̄|| ∧_∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
.|| || (´Д` ) < http://www.dvd01.hamstar.jp だ!
/ \ \___________
|| ||
|| ||
__ //_ //___
/ // // /
/  ̄  ̄ //
|| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|| ||
|| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|| ||
|| 教卓 || ||
|| ||
0404nobodyさん
03/06/02 10:35ID:azLkJHuzいやいや、なんで<=を使ってるかが知りたいの?
ifって偽だと実行しないでしょ?
$retryは最終的に0になるわけだから、<=は必要ないだろ。
ってかスレ違いって分かってるので、逝ってきます。
0405nobodyさん
03/06/02 10:39ID:7y9vki3nやっぱり逝くしかないな…。
0406直リン
03/06/02 11:10ID:mGHfwiJV0409nobodyさん
03/06/02 12:07ID:???いや・・・だからさ・・・
全体のソース読んでないんで分からないんだけど。
マイナスになる可能性があるかもしれないんでしょ?
--$retry <= 0
この条件だと、$retryがもし0だったら・・・
-1 <= 0
こんな判定になるし。
0が入る訳がないソースだったとしても、
ちゃんと条件書いてる方が、見た目分かりやすいってのもある。
そして、スレ違いだから、やっぱ逝くべき。
0412nobodyさん
03/06/02 12:47ID:YkiHze2nうおっ!キツイ一言だな…。
でもこのスレのヤシらはなんか優しい…。
すっきりしたら逝くから、すっきりさせろYO!
なんで-1になるんだ?
粘着房だな…。
0413nobodyさん
03/06/02 13:02ID:???だから・・・・
--$retry <= 0
↑これだけ見せられて、-1になるか、ならないかって言われても、
分からない訳なのよ。
どのソースみて、言ってる訳?
とにかく、その一行を見る限りでは、-1になる可能性はある。
何度も言うようにスレ違いだから、優しいうちに逝っとけ。
0414動画直リン
03/06/02 13:10ID:mGHfwiJV0416nobodyさん
03/06/02 13:43ID:???気がするであって、気にする奴が本当に気にしなきゃいけない場合はアセンブラで書く。
0417_
03/06/02 14:38ID:???0418_
03/06/02 16:09ID:???0419_
03/06/02 19:13ID:???0421nobodyさん
03/06/17 05:57ID:???これって使っても平気ですか?
0422nobodyさん
03/06/22 16:13ID:???0423nobodyさん
03/07/07 19:32ID:???20 Open "Text1.txt" For Output As #1
30 Print #1,"Write file."
40 Close #1
ファイルロックのためのtmpファイル作成しようと思ったんですが、
プログラム内で擬似マルチタスクを作成している時といないときがあるので、
flock関数みたいなものがあれば効率が上がると思うのですが、
やはりrename形の方が安全で軽いのでしょうか?
0424なぞなぞ先生
03/07/08 06:24ID:???0425nobodyさん
03/07/08 12:02ID:???0427nobodyさん
03/07/08 12:19ID:???0428nobodyさん
03/07/08 15:54ID:???0429nobodyさん
03/07/08 15:58ID:???0431nobodyさん
03/07/10 16:21ID:QDkm5VXPflock使えるサーバなんだけど、書き込み中はロックするっていう
対象のファイルをflockの引数にするのと、別のダミーファイルを
flockの引数にするのとあるでしょ。どっちがいいのでつか。
0432nobodyさん
03/07/10 17:46ID:???処理全体にかけたいなら後者の方が良いかと。
0433nobodyさん
03/07/10 21:42ID:???0435nobodyさん
03/07/11 11:17ID:???0437なぞなぞ先生
03/07/15 06:43ID:???完全に同時にプロセスが発生することはないよね?
マルチタスクってのもマルチスレッドってのも基本的に擬似的に行っているもので、
結局は1つのプロセスが司っている処理って聞いたことがあったような。
そうすると、OSがダウンしない限りrename型の排他処理
rename
open
処理
close
rename
は完璧に有効だと思うんだが。
と思ったけど、それを言い始めたらキリが無いかw
うーん、、、しかしたまに2chで1001を超えるのは何でだろう。
ロック解除してから1001のチェックをしているのかな。。。
最近うなされて困ってます。変な文&長文すまん。
0438nobodyさん
03/07/15 06:44ID:???氏のう。。。。
0439山崎 渉
03/07/15 11:08ID:???__∧_∧_
|( ^^ )| <寝るぽ(^^)
|\⌒⌒⌒\
\ |⌒⌒⌒~| 山崎渉
~ ̄ ̄ ̄ ̄
0440nobodyさん
03/07/15 19:03ID:???レスが1000を超えるのはdatファイルへの書き込みと、
レスポンス数のチェック(書き込み禁止処理)がアトミックにできないから。
実際には、二つの処理に結構な間があると思う。
0441nobodyさん
03/07/15 22:40ID:???| |
∧_∧ | | / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
( ´ー`)// < 先生!
/ / | アトミックって何ですか?
/ /| / \___________
__| | .| | __
\  ̄ ̄ ̄ ̄ ̄ \
||\ \
||\|| ̄ ̄ ̄ ̄ ̄ ̄ ̄|| ̄
|| || ̄ ̄ ̄ ̄ ̄ ̄ ̄||
.|| ||
0442nobodyさん
03/07/15 23:25ID:???他のプロセスが割り込めない極小時間(ワンステップ)で操作。
にしといてくださいな。
0443nobodyさん
03/07/16 07:27ID:???ましてやファイルロックの話題ならなおさら
0444437
03/07/16 08:09ID:???ファイルロック中に何らかの処理(たとえば別ファイルにHTML書き出しやHTML化待ちDATリストへの追加)
をすれば、"アトミック"は存在しないと思うのですが。
下手な考えスマソ。。。
0445440
03/07/16 22:09ID:???ああっと、flockが頭にあったので、、
renameが理想的なロックとして動作するとしたら>>437で可能だと思います。
(OSがlinuxの場合は壊れたりするけど…)
2chとしては、1000で止まらなくても(多少レスが多く付いても)構わないのかも。
(ロックする時間が増える→待ちプロセス数が増える→サーバ負荷が増えるよりは。)
0446437
03/07/17 00:22ID:???2chみたいな大規模な掲示板だとここが問題なんですね。
ぐっすり眠れそうな気がしました。レスありがとうございました。
0447nobodyさん
03/07/19 14:28ID:???スレッドキー(ファイル名)決定と、ファイル作成(書き込み)を別の場所で
行っている事がほとんどなので、同時にスレ立てが発生するとスレッドが
合体する可能性がある。
半年前あたり2chでもちょっと問題になってた。
実際としては2ch以外で問題になることは無いと思うけどね。
0449nobodyさん
03/07/20 09:18ID:???そういうことじゃない。
スクリプトの中でキー決定からファイル作成までの間に
いろいろな処理があって、同時スレ立ての一方がファイル作成前に
もう一方がそのキーのスレがあるか確認して存在しないと
判断してしまう時差の問題が起こりえるということ。
0450nobodyさん
03/07/26 13:13ID:GHzBAdl/具体的に何をすれば良いのでしょうか?
flock と言う名前のディレクトリを
作って、ロックしたいファイルに
置いとけば良いのでしょうか?
すいませんが、まるっきりの初心者ですので、
教えて下さい。
0453_
03/07/26 13:55ID:???0454nobodyさん
03/07/26 18:00ID:???flockするファイルのあるディレクトリのパーミッションは任意たんでよいですか?
自分の中で最高の条件を満たすレンタル鯖がflock使えないとかなりへこむ。。。
結局rename型のlockにしてみたんだが、鯖の負荷とか考えたくないなぁ。
ブロードバンド回線開通したら絶対鯖立てたい。
と言う独り言でした。また来週。
0455nobodyさん
03/07/26 22:03ID:???flockも使うのが最強ですかね?
0456nobodyさん
03/07/26 22:40ID:???0457nobodyさん
03/07/27 01:31ID:???ハァ、Webプログラマーってどうして馬鹿ばっか集まるんだ。
排他制御に強い/弱いはない。正しい/駄目のどちらかだ。
駄目なものをいくつ重ねても駄目なものは駄目。正しい方法を複数使う必要はない。
0458nobodyさん
03/07/27 03:14ID:???0459nobodyさん
03/07/27 09:30ID:???0460nobodyさん
03/07/27 20:51ID:???http://tv3.2ch.net/test/read.cgi/geino/1050253651/377
0461nobodyさん
03/08/04 22:07ID:???0462nobodyさん
03/08/06 01:55ID:pOGj2Sy20463nobodyさん
03/08/06 01:56ID:pOGj2Sy20464nobodyさん
03/08/06 01:56ID:pOGj2Sy20465nobodyさん
03/08/07 14:03ID:fxtSTKINuse Fcntl;
をしといて、
sysopen
を使ってLOCK_EXとか呼べないかな。
0466nobodyさん
03/08/07 14:18ID:???LOCK_EXは定数(を返すだけのsub)
0467nobodyさん
03/08/07 15:00ID:???sysopen FILE,"hoge",O_RDWR|O_CREAT|LOCK_EX;
みたいなことできるかってこと?
試してみてね。
俺は知らん。
0470nobodyさん
03/08/09 22:15ID:???use IO::File::fock;
my $fh = new IO::File::fock('file','>>');
0471山崎 渉
03/08/15 22:42ID:???│ ^ ^ │<これからも僕を応援して下さいね(^^)。
⊂| |つ
(_)(_) 山崎パン
0472nobodyさん
03/08/24 11:20ID:???追記の場合って、どうするのが一番確実で負荷がかかんないんでしょうか?
僕は、データを編集する場合と同じように、以下のようにしちゃってますが。use Fcntl qw(:flock);
#万が一リネーム失敗したときのために、ユニークなファイル名にしておく
$tmpfile = "$datafile".".$$.". time() .".csv";
#ロックファイルを作成する(★注:ロックファイルは、各CSVごとにユニークに)
open (LOCKF, ">$datafile"."_lockf") or die("cannot open:$!");
flock (LOCKF, LOCK_EX); #ロックファイルをflockする
open(IN, "< $datafile") or die("cannot open:$!"); # 読みのみモードで開く
open(TMP,"> $tmpfile"); #テンポラリファイルを作成
while ($line = <IN>){
$line .= <IN> while ($line =~ tr/"// % 2 and !eof(IN));
$line =~ s/(?:\x0D\x0A|[\x0D\x0A])?$/,/;
@values = map {/^"(.*)"$/s ? scalar($_ = $1, s/""/"/g, $_) : $_}
($line =~ /("[^"]*(?:""[^"]*)*"|[^,]*),/g);
#必要なものだけをEUCにして、出力時にSJISにする
foreach $value (@values){
&jcode::convert(\$value, "euc");
};
#CSV形式に変換
$newline = join ',', map {(s/"/""/g or /[\r\n,]/) ? qq("$_") : $_} @values;
print TMP "$newline\n" ;#テンポラリファイルに1レコード書き込み
}
print TMP "新しい行" . "\n";
close TMP;
close IN;
unlink $datafile;
rename ($tmpfile, $datafile) or die ("cannot rename : $!");
close LOCKF;
0473472
03/08/24 11:25ID:xfHM1yWk訂正。
↓これでどうでしょか?
use Fcntl qw(:flock);
#万が一リネーム失敗したときのために、ユニークなファイル名にしておく
$tmpfile = "$datafile".".$$.". time() .".csv";
#ロックファイルを作成する(★注:ロックファイルは、各CSVごとにユニークに)
open (LOCKF, ">$datafile"."_lockf") or die("cannot open:$!");
flock (LOCKF, LOCK_EX); #ロックファイルをflockする
open(IN, "< $datafile") or die("cannot open:$!"); # 読みのみモードで開く
open(TMP,"> $tmpfile"); #テンポラリファイルを作成
while ($line = <IN>){
print TMP $line ;
}
print TMP "新しい行" . "\n";
close TMP;
close IN;
unlink $datafile;
rename ($tmpfile, $datafile) or die ("cannot rename : $!");
close LOCKF;
0474472
03/08/24 11:57ID:xfHM1yWk単純に、
use Fcntl qw(:flock);
open(OUT, "+< $datafile");
flock (LOCKF, LOCK_EX);
truncate(OUT, 0); # ファイルサイズを0バイトにする
seek(OUT, 0, 0); # ファイルポインタを先頭にセット
print OUT "新しい行" . "\n";; # 書き込む
close(OUT); # closeすれば自動でロック解除
・・・・どっちがいいのでしょうか・・・?
0475nobodyさん
03/08/24 12:53ID:???追記なら
use Fcntl qw(:flock);
open(OUT, ">>$datafile");
flock (OUT, LOCK_EX);
seek(OUT, 0, 2); # ファイルポインタを最後尾にセット(念のため)
print OUT "新しい行" . "\n";; # 書き込む
close(OUT); # closeすれば自動でロック解除
--
# 私はこんな感じ(Win不可)
use FileHnadle;
my $fh = new FileHandle($datafile, O_WRONLY|O_CREAT|O_APPEND|O_EXLOCK) or die;
print $fh '新しい行', "\n";
close($fh);
IO::Fileでもいいんだけど、趣味でFileHandle使ってます。
0476nobodyさん
03/08/27 11:26ID:???open(LOG, ">$logfile") or &error("Open Error : $logfile");
flock(LOG, 2);
seek(LOG, 0, 2);
my(@lines) = <LOG>;
(if($agent =~ /MSIE 3/i) { $agent = 'MSIE 3'; }のような置換とか)
while($max-1 < @lines) { pop(@lines); }
unshift(@lines, "$agent<>$os<>$host<>$referer<>$hour<>$doc_uri<>\n");
unshift(@lines, "$addr\n");
print LOG @lines;
close(LOG);
こうすると書き込み時にログが一旦全部消えてしまい、
取得した最後のログ一行(先頭行に最終アクセスIPがあるので正確には二行)のみになってしまいます。
何処が悪いのでしょうか…
因みに元スクリプトではログを配列に読み込んだ時点で一旦閉じ、
処理後もう一度開いて書き込みという風になってたのですが、
これだと処理中に書き込まれたら駄目そうな気がしたので上のように書き換えたのです。
0477nobodyさん
03/08/27 19:09ID:???lockどうこうより、while がおかしいのでは?
$max-1 < @lines がどういう比較かわからんけど、自分で
pop(@lines);して削除しちゃってるじゃないの
常にwhileが真で全行削除になってその後unshiftで2行追加してるだけでは?
0478nobodyさん
03/08/27 21:08ID:???'>'でオープンすると?
・ファイルの中身を切り詰める。
・書き込み専用でオープンする(ファイルが無ければ作成)。
>seek(LOG, 0, 2);
この意味は?
・フィル最後尾にファイルハンドルを移動する。
さすがに読めません。
0479nobodyさん
03/08/27 21:09ID:???flock(LOG, 2);
my (@lines) = <LOG>;
(ロックスレなので、、略)
seek(LOG, 0, 0);
truncate(LOG, 0);
print LOG @lines;
close(LOG);
上の書き方では、seekとtruncateの間で終了させられると、
ファイルの中身が失う危険性があるから、
seek(LOG, 0, 0);
print LOG @lines;
truncate(LOG, ftell(LOG));
close(LOG);
と書くといいらしいです。(実際はどうなんでしょ?)
http://www.kt.rim.or.jp/%7ekbk/perl5.005/perlfaq5.html#How_come_when_I_open_the_file_re
http://www.kt.rim.or.jp/%7ekbk/perl5.005/perlfaq5.html#I_still_don_t_get_locking_I_jus
クックブック 7.11
ttp://homepage1.nifty.com/glass/tom_neko/web/web_04.html
0480479
03/08/27 22:53ID:???間違いでした。以下の通り。
truncate(LOG, tell(LOG));
0481nobodyさん
03/08/28 11:06ID:???だめなの?
0482nobodyさん
03/08/31 01:47ID:3rubdTEFuse DB_File;
use Fcntl;
open DAT,"lockfile";
flock(DAT,LOCK_EX);
tie(%hash,'DB_File',"dbfile",O_RDWR|O_CREAT,0666
---DBM代入処理
としてロックしてました。
lockfileというファイルへの排他ロックを取得しているのは
わかるんだけど、それがどうしてDBMのdbfileへのロックと
なるのかわからん。
■ このスレッドは過去ログ倉庫に格納されています