• ベストアンサー

ファイルロックの確認

PHPで掲示板を作っています。バージョンは5? (php.exeファイルのバージョンは5.2.1.1です。) ファイルロックについて、下記2点を教えてください。 同時書き込みによるログファイルの破損を防ぐため、ロック専用ファイルによるロックとアンロックの仕組みを作りました。 正常に稼動しているか、以下の方法でチェックしました。 1.ブラウザを2つ開く 2.両方とも書き込みボタンを押すだけの状態にする 3.両方のブラウザ(フォーム)の「書き込み」ボタンをすばやく続けてクリックする この方法だと、3で2個のボタンをクリックする間のタイムラグがあり、“同時”書き込みは難しいように思います。 他に方法があるのでしょうか? ////////// ロックファイル:lock/lock.php(755) --<?php --$lockfile = '.lock/lock.txt'; --$fp = fopen($lockfile,"w"); --flock($fp,LOCK_EX); --?> アンロックファイル:lock/unlock.php(755) --<?php --fclose($fp); --?> ロック用ファイル:lock.txt(644) ロックディレクトリ:lock(755) 動作ファイル:bbs.php --<?php --require_once './lock/lock.php'; --掲示板の処理 --require_once './lock/unlock.php'; --?> ロックのファイルを別ディレクトリに置くことは可能でしょうか? 可能であれば、パーミッションはどのようにすればいいのでしょうか? 現状、前述の方法でログが破損するかチェックしても異常ありません。 また、ロック関連の記述を削除してチェックしても異常ありませんので、ロックが正常に稼動しているのかどうか確認できない状態です。 PHPは始めたばかりですので、おかしなことを言っている箇所もあるかもしれませんが、宜しくお願いします。

  • PHP
  • 回答数1
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

ロックのテストをする時は専用のプログラムを書いた方が確実じゃないかな?と思います。 a.php <?php --require_once './lock/lock.php'; sleep(60); $fp = fopen("./test.log","a"); fwrite($fp,"A"); fclose($fp); --require_once './lock/unlock.php'; ?> b.php <?php --require_once './lock/lock.php'; $fp = fopen("./test.log","a"); fwrite($fp,"B"); fclose($fp); --require_once './lock/unlock.php'; ?> こんなんでテストできそうな気がしますがいかがでしょうか。

ka-kichi
質問者

お礼

ソースまでご提示いただき、ありがとうございます。 a.phpは、ロックして60秒待ち、test.logに「a」と書き込む。 b.phpは、遅延なく「b」と書き込む。 a.phpを実行した後、60秒以内にb.phpを実行すれば、同時アクセスが実現できる。 という解釈でいいのでしょうか? これを実行すると、a.phpはしばらく(60秒間)反応がなく、b.phpも反応がない。 60秒程待つと、a.phpの処理が終わり、その直後にb.phpの処理も終わる。 test.logを見ると、「ab」と記録されている。 この結果から、ロック機能が正常に働いていると考えていいのでしょうか? なにぶん素人なので、いまいち自信がありません。 宜しくお願いいたします。

関連するQ&A

  • PHPのファイルロックについて

    関数flock();について調べてたのですが、 結局、イマイチ使い所がわかりませんでした。 とりあえずCGIを手本として以下のロックを作ってみたのですが、 もし、flockを使うとしたらどのように使うのかアドバイスして欲しいと思っています。 ↓参考プログラム(echo部は進行を表示するためのもの) <?php define ("LOCK_FILE","./lock/lock.txt"); Lock(); Unlock(); //ロック function Lock(){ if(file_exists(LOCK_FILE)){ if(date(U) - filemtime(LOCK_FILE) > 30){ unlink(LOCK_FILE); echo("古いロック削除<br>"); } } $retry = 5; while(file_exists(LOCK_FILE)){ if($retry <= 0){ echo ("error<br>"); exit; } $retry--; sleep(1); } $lockfile = fopen(LOCK_FILE,"w"); fclose($lockfile); echo("ロック完了<br>"); } //アンロック function UnLock(){ unlink(LOCK_FILE); echo("ロック解除<br>"); } ?>

    • 締切済み
    • PHP
  • ロックファイルの自動削除

    現在、以下のように記述されており、 ロックされてから2秒後に解除されるはずが 2秒後の最初の投稿の際にはロックファイルが存在している旨のメッセージが表示され、 (その際にロックファイルが自動削除されるが投稿はできない) その次の投稿から投稿が可能になるのですが、 2秒後の投稿の際にそのロックファイルを自動削除し、 投稿もできるようにするにはどのように書きかえたらいいのかお教えいただけませんか? ## --- ファイルロック sub lock { if ($_[0]) { $lock_file = $_[0]; } else { $lock_file = $lockfile; } if ($lock_file ne "") { local($flag) = 0; foreach (1 .. 5) { if (-e $lock_file) { sleep(1); } else { open(LOCK,">$lock_file"); close(LOCK); $flag = 1; last; } } if ($flag == 0) { $past_lock = -M "$lock_file"; if ($past_lock * 24 * 60 * 60> 2) { &unlock("$lock_file"); } &error("システムエラー","アクセスが集中しているため、タイムアウトとなりました。(ロックファイルが存在しています)"); } } } ## --- ファイルロック解除 sub unlock { if ($_[0]) { $lock_file = $_[0]; } else { $lock_file = $lockfile; } if (-e $lock_file) { unlink($lock_file); } }

    • ベストアンサー
    • CGI
  • phpのlock処理について

    phpのlock処理について 頻繁に書き込みされるファイルが飛ばないようにロックをしているのですが、 (アクセスログを保存) phpのロック処理を調べていると 一方ではこれでよい、もう一方ではこれでは意味がないなど 色々な事が書かれており、いまいち理解できません。 wモードで開くと強固なロックは不可能なのでしょうか。 以下のようにしているのですが ロックの意味はないでしょうか。 //ロック専用ファイルを開く $flock=fopen("lock.txt","w"); //ロック専用ファイルをロック flock($flock,LOCK_EX); //書き込むファイルを連結して代入 $lineall = implode('', $lines); //書き込み用のファイルを開く $fp=fopen($log_file,"w"); fwrite($fp, $lineall); fclose($fp); //ロック用ファイルのロック解除 flock($flock, LOCK_UN); fclose($flock); プログラムが1から私が作成したものではなく、 ちょくちょく消えてしまうことからロック処理をしたいのと 処理の問題でwモードでの書き込みでないとどうもゴミが入ってしまうようですので (r+でやってみましたが空行などのゴミが沢山入ってしまいました) wモードでの強固なロック方法があればと思うのですが・・・。 お手数をおかけしますがご教授いただけますと幸いです。

    • ベストアンサー
    • PHP
  • ロック専用ファイルについて

    ロック専用ファイルについて すいません、またまた教えてください。m(_ _)m 一つのページに掲示板とカウンターの2つの別々のコードを含めようとしてます。 (現在、掲示板は問題なく動作していて、掲示板のコードの後に カウンターのコードを書こうとしています。) 掲示板にロック専用ファイルを作って、下記のようにしています。 $lock_fp = fopen("lock.txt", "w"); flock($lock_fp, LOCK_EX); ~掲示板ログの更新処理~ fclose($lock_fp); この後に、カウンターのコードを書いて、同じようにロック専用ファイルを使った 排他ロックの仕組みにしたいと思いましたが、そこでふと疑問が・・・。 flock()の排他ロック開始の行 ~ ロック解除の行(ロックファイルのファイルポインタ破棄の行) の間に書かれている全ての処理は、他の人がアクセスしているときは 自分の番になるまで行われないと思うのですが、 ロック解除の行の後に書かれている他のPHPの処理は普通に進んでいくのでしょうか? だとすれば、カウンター用のロック専用ファイルは 掲示板用のそれ(lock.txt)とは別のもの用意しないといけないと思うのですが、 その考え方で合っていますか? ものすごく基本的な質問な気がするのですが、参考書や参考サイトを見ても なかなか回答を上手に見つけられず困っています。 お手数ですが、ご教授ください。よろしくお願いいたします。

    • ベストアンサー
    • PHP
  • $retry--の「--」の意味は?

    $retry--の「--」の意味は? ファイルロックについて調べていたら function lock(){ //ロックファイル $file = "lock.txt"; $lockDir= "lock/"; $lockfile = $lockDir . $file; //再挑戦回数 $retry = 3; //30秒以上古いロックは削除する if (file_exists($lockfile)) { $mtime = filemtime($lockfile); if ($mtime < time() - 30) { unlock($file); } } //ロック用ディレクトリを作成する while (!@mkdir($lockfile, 0755)) { if ($retry-- <= 0) { print "只今混雑しています。";exit;} sleep(1); } } のコードを見つけました。「$retry--」の2回ハイフンでどんな意味なのでしょうか? ちなみに他に書き換えるとしたらどんなコードでかけるのでしょうか?

    • ベストアンサー
    • PHP
  • ロックしたディレクトリが消えない(?)

    flock関数を使い、 $lockfile="./lock/lock.loc"; sub lock { foreach $i (1..6) { . . . if(open(LOCK,">$lockfile")){ if (flock(LOCK,6)) { $lock_flag = 1; last ; } } . . . } } という風にし、メインルーチンで&lockを実行し、ファイルロックしたのですが、flock(LOCK, 8)を使い忘れ、あとでFFFTPを使ってこれを消そうとしても、なにやらディレクトリが永遠に続いている感じになってしまい消せません。 /lock/lock.loc/lock.loc/lock.loc/lock.loc/lock.loc/... という風になっています。 それと元からlock/lock.locというディレクトリが存在したままflockを使ってしまったかどうかはちょっと確認していなかったのですが、使う前にあったとしたらlock.locはファイルではなく、ディレクトリです。 (mrdirを使ったロックなどをいろいろ試していたためです。) うまく説明できなかったのですが、どうすればこれは消せますか?後でflock(LOCK, 8)をやっても直りません・・ アップしたサーバーは@niftyです

    • ベストアンサー
    • Perl
  • flockのファイル保持について

    一つのブラウザで以下のプログラムを動かしつつ、、 ---- lock.php ---- <?php $filnam = "./log.txt"; $fp = fopen($filnam,"w"); flock($fp, LOCK_SH); ?> ここでしばらく待つ。 <?php sleep(30); flose($fp); ?> ------------------ もう一つのブラウザで ---- if.php ---- <?php $filnam = "./log.txt"; $fp = fopen($filnam,"w"); // ・・・(1) if(!flock($fp, LOCK_EX)){ print ("ロックされています。<BR>"); }else{ print ("ロックされていません。<BR>"); } ?> ------------------ を動かしました。 期待していた結果は 「ロックされています。」の表示です。 ですが、lock.phpプログラムの終了を、(1)の部分で待っているようで、lock.phpプログラムが終了後、「ロックされていません。」の表示になります。 ロックされていたらすぐに「ロックされています。」の表示を出したいのですが、どうしたらいいでしょうか?何か勘違いをしている部分があればご教授ください。

    • 締切済み
    • PHP
  • ロックファイルの確実性について

    たとえばカウンタなどを作ろうと思ったとき、データを保存する ファイルを2重にアクセスできないようにするために、ロックファ イルを用意するのが一般的だと思います。 しかし、単にロックファイルを作って、それを if (-e $lockfile) {~~} などとやっても、けっこう頻繁に2重アクセスされてしまいます。 実際、以前、1000アクセス/日あるページを運営していたとき、上の 方法では3日に1回は壊れました。 上の方法は、理論上はありえないはずなのに、なぜおこるのでしょうか? また、ロックファイルではなくロックディレクトリを作って、 unless (mkdir ("./lock", 0777)) {~~} と行うことによっても、同様の判定が可能かと思いますが、 こちらの方法でもやはり2重アクセスが発生してしまうことが あるのでしょうか? その確立は、ロックファイルと同一レベル でしょうか? また、発生するならば、ディレクトリシステム上に 同じ名前のディレクトリが2つ存在することになるのでしょうか? もしわかる方がいらっしゃいましたら、ぜひ教えてください。

    • ベストアンサー
    • CGI
  • ファイルの書き込みについて

    ファイルの書き込みに関する質問です。 下のコードでは、 3行目「$ptr=fopen("kekka.txt", "w"); //ファイルを開く」 に問題があるというエラーが出ます。 しかし、文法的には問題はないと思うのですが・・・。 サーバーには、"kekka.txt"というファイルが置いてあります。 何かアドバイスがありましたら、よろしくお願いいたします。 <?php $x = "こんにちは";  $ptr=fopen("kekka.txt", "w");   //ファイルを開く    flock($ptr, LOCK_EX);      //ファイルをロックする      fputs($ptr, $x);      //書込む    flock($ptr, LOCK_UN);       //ロックを解除する  fclose($ptr);            //ファイルを閉じる ?>

    • ベストアンサー
    • PHP
  • LOCK_EXはifの条件になり得るのか?

    $fp = fopen("/tmp/lock.txt", "r+"); if (flock($fp, LOCK_EX)) { // 排他ロックを確保します ftruncate($fp, 0); // ファイルを切り詰めます fwrite($fp, "ここで何かを書きます\n"); fflush($fp); // 出力をフラッシュしてからロックを解放します flock($fp, LOCK_UN); // ロックを解放します } else { echo "ファイルを取得できません!"; } fclose($fp); PHPのマニュアルサイトに書いてあった例文なのですが、たぶんロックできなかった場合は「ファイルを取得できません!」に出るようにするというものだと思います。 ただ、LOCK_EXはロックできない場合は、ロックできるようになるまで待ちますよね? だとすると、このif文ってelseは機能しないと思うんですが、どうなんでしょうか? もしかしてLOCK_EXは時間制限があって、待ち状態が何分も続くとタイムアウトとしてFalseを返す? そのときにelseが動くということでしょうか? この例文の下にLOCK_NBを使ったものもあるので、LOCK_EXの動作を勘違いしてるとは思えません。 この例文はどのタイミングの時にFalseを返して、elseが動くのでしょうか? http://php.net/manual/ja/function.flock.php

    • 締切済み
    • PHP

専門家に質問してみよう