• 締切済み

ファイル書き込みでたまにデータが全部消えてしまう。

phpでアクセス解析を作っているのですが、 解析データをログファイルに書き込みする際に たまにデータが全部消えてしまう現象に陥りました。 下記コードでログファイルに書き込み処理をしています。 どなたか原因が分かる方、ご教授お願いいたします。 // ログデータ処理 $logdata = file($counter->logfile); list($time,$host) = explode("\t",$logdata[0]);// 比較のため直前のホスト取得 if($host != $counter->host and // 連続アクセスは処理しない !$out_flag){// 除外ホストは処理しない $str = time()."\t".// 時間 $counter->host."\t".// ホスト $counter->agent."\t".// ユーザーエージェント $counter->referer."\t".// リンク元 "\t\n"; $lp = fopen($counter->logfile,"w"); $lock = flock($lp,LOCK_EX); if($lock){ fputs($lp,$str); $i = 1; foreach($logdata as $value){ fputs($lp,$value); $i++; if($i >= $counter->loglimit){break;}// ログ上限に達したら抜ける } } flock($lp,LOCK_UN); fclose($lp); }

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

みんなの回答

  • shimix
  • ベストアンサー率54% (865/1590)
回答No.1

fopen($counter->logfile,"w");の時点でファイルは空になっていますから、このタイミングで(ロックする前に)他からfile()で読んだら何もない状態です。 比較のための直前ホストの取得などはfile()で読み込んだものでもいいですが、実際に「書き込み」をするときには、"rw"で開く→ロック→全行を再取得→ファイルポインタを先頭に戻す→追加データ+再取得データを書き込み→ロック解除でないとマズイのでは?

hunter_999
質問者

補足

ご解答ありがとうございます。 具体的なコードが分からず困っております。 もし差し支えなければ教えていただければ幸いです。 どうかよろしくお願いいたします。

関連するQ&A

  • PHPの勉強として掲示板を作成しているのですが、謎の二重書き込みに出会

    PHPの勉強として掲示板を作成しているのですが、謎の二重書き込みに出会い躓いています。 下記はテストとして書いた、状況が再現されるソースです。 <?php $filename = './test.dat'; if($_REQUEST) { $data = file($filename); $newdata = "{$_REQUEST['newdata']}\n"; $logfile = @fopen($filename, "r+"); flock($logfile, LOCK_EX); foreach($data as $value) { fputs($logfile, $value); } fputs($logfile, $newdata); flock($logfile, LOCK_UN); fclose($logfile); } ?> <html> <head><title>TEST</title></head> <body> <form action="test.php"> <input type="text" name="newdata"> <input type="submit"> </form> </body> </html> 5、6行目で $newdata = "{$_REQUEST['newdata']}\n"; $data[] = $newdata; とした場合、DATを逆順にして $newdata = $_REQUEST['newdata']; $array_unshift = $newdata; とした場合、また、そこで追加せずに書き込み処理を $logfile = @fopen($filename, "r+"); while(!feof($logfile)) { $data[] = fgets($logfile); } fputs($logfile,$newdata); foreach($data as $value) { fputs($logfile, $value); } とした場合、など…どうやってもなぜか同じ症状が出ます。 しかももっと不思議なのは、どこでおかしくなっているのか調べようと思い途中にprint_r($data)を入れると、場所によってはなぜか二重書き込みが起きなかったりするのです。 検索しても同じ状況は見つけられずどうしたものかと悩んでおります。 情報が足りないかもしれませんが、何か気づいた方がいましたら教えてください。よろしくお願いします。

    • ベストアンサー
    • PHP
  • 書き込みデータフォルダの切り替え

    jump.php ./001/log ./002/log ----------------------------- 下記PHPのログファイルの書き込みをフォームから(001・002・・) $name=$_POST[name]; で得た値のフォルダへ振り分けてデータの書き込みしたいのですが うまくできません。 ----------------------------- 改変前 $logfile = $logdir."/$y-$m-$d.txt"; 改変後 $logfile = $name."/".$logdir."/$y-$m-$d.txt"; ----------------------------- ご指導よろしくお願いいたします ----------------------------- $logdir ="log"; // if($_POST[r]){ $y=$_POST[y]; $m=$_POST[m]; $d=$_POST[d]; $H=$_POST[H]; $i=$_POST[i]; $word=$_POST[word]; $name=$_POST[name]; $pass=$_POST[pass]; if($pass != $adpass){die("パスワードが違います"); } if( eregi("[^0-9]",$d) || eregi("[^0-9]",$m) || eregi("[^0-9]",$y)){ die("半角数字のみ有効です。"); } if(!checkdate($m,$d,$y)){die("その日は存在しません。"); } $logfile = $name."/".$logdir."/$y-$m-$d.txt"; if(file_exists($logfile)){ $lines = file($logfile); $fp = @fopen($logfile,"w"); for($j=0;$j<count($lines);$j++){ fputs($fp,$lines[$j]); } @fputs($fp,$H.":".$i.$word.$name."\n"); @fclose($fp); }else{ $fp = @fopen($logfile,"w"); @fputs($fp,$H.":".$i.$word.$name."\n"); @fclose($fp); } header("Location: $_SERVER[PHP_SELF]"); exit; } -----------------------------

    • 締切済み
    • PHP
  • CSVファイルの上書き

    CSVファイルを$line[0] = $nowの時、上書きするということをしたいのですが、array_spliceでうまくいきません。 アドバイスお願いします。 $fp = fopen('log/order.csv', 'a+'); flock($fp,LOCK_EX); if ($fp) { require_once( "./common.php" ); $AddressData = LoadTextFile( "./log/order.csv", "SJIS", "SJIS" ); if ( $AddressData == false ) { exit; } else { for ( $i = 0; $i < sizeof( $AddressData ); $i++ ) { $line = explode( ",", $AddressData[ $i ] ); if($line[0] = $now){ array_splice($line, 1, 3, array("1","2","3")); #fputs($fp, $buf2); flock($fp,LOCK_UN); fclose($fp); } } } }

    • 締切済み
    • PHP
  • 新しいログの書き込み

    新しいログを追加で上に書き込む方法はどのようにしたらよいのかアイディアがありません。 ご教授願います。 if($mode eq "html"){ flock(FH, LOCK_EX); open(FH,"${datafile}"); @html = <FH>; close(FH); flock(FH, LOCK_NB); $html = join('',@html); @html = split(/$chtml/ , $html); $html[1] = $data; $html = join($chtml,@html); flock(FH, LOCK_EX); open(FH,">$datafile"); print FH $html; close(FH); flock(FH, LOCK_NB);

  • 【PHP】 書込みされた事を知らせる為のアイコン表示

    私の理想のイメージは、abc.php ファイルの掲示板に書込み(新規・返信)されたら、zyx.php ファイルの方で その abc.php ファイルの掲示板で書込みされた事を知らせる為のマーク up.gif (アイコン)を、書き込まれた日から 24時間(1日)の間表示させたいのです。 ◆ log.txt ファイル(掲示板の書込みログ) 1,みかん君,2008/04/16 15:19:14 ・ 3,りんご君,2008/04/13 22:19:32 ・ ・ 6,ぶどう君,2008/04/11 08:19:48 ・ ・ 以下省略 【 log.txt ファイルの補助説明 】 ※ 「 , 」(カンマ)で区切りを付けてます。 ※ インデックス,名前,日付 と言う順に配列がなっています。 ※ log.txt ファイルは、上から最新順に書き込まれるようにしてあります。 ※ インデックス($no) 名前($name) 内容($date)と配列がなっています。 ◆ abc.php ファイル(掲示板ページ) $fp = fopen("log.txt","a"); flock($fp, LOCK_EX); $data = implode( "," , array($no,$name,$date."\n") ); fputs($fp,$data); flock($fp, LOCK_UN); fclose($fp); 【 log.txt ファイルの補助説明 】 ※ 掲示板での書き込み処理です。 ◆ zyx.php ファイル(up.gif (アイコン)を表示させたいページ) <? $files = file("log.txt"); $logdata = $files[0]; list($no,$name,$date) = explode( "," , $logdata); if($no != ){ } ?> ここまではやってみましたが、ここから、どのようにしたらよいのか分らないので教えて下さい? また、if で、どのように条件を定義してよいかも分りません。宜しくお願い致します。

    • ベストアンサー
    • PHP
  • CSVデータを読み込み、ファイルにカテゴリを分けて書きこむ

    CSVファイル例 01,0101,○○○,○○○□□,010101, 01,0102,○○○,○○○■□,010102, 02,0201,○○○,○○○□□,020101, ・・・・・ というファイルがあったとすると、 1番目の「01」「02」と、分けて別のファイルに保存がしたいです。 書き込み自体は出来るようなのですが、なぜかループが、番号ごとに1回しかされずに、 log/01.cgi 01<>0101<>○○○<>○○○□□<>010101 log/01.cgi 02<>0201<>○○○<>○○○□□<>020101 となってしまい、全ての生成したファイルには1行しか格納されていません。 ちなみに、csvファイルは1万行近くあります。 ソースはこのような感じです。 $log = "△△△.csv"; # ログ名 $lines = file("$log"); foreach ($lines as $l) { $line = explode(",",$l); $push_line = $line[0]."<>".$line[1]."<>".$line[2]."<>".$line[3]."<>".$line[4]."<>\n"; $LOG[$line[0]] .= $push_line; $cate = $line[0].",,".$line[1]; # サブカテゴリ用 $LOG[$cate] .= $push_line; # カテゴリ用ログを保存 } なお、csvファイルは、 01・・・ 02・・・ 01・・・ 03・・・ のようになっているため、全ての行を読み込むことはしていると思います。 しかし、ログファイルにはなぜか1行分しか書き込まれていません。書き込みの文は以下になります。 foreach($LOG as $key => $value){ $explode = explode(",,",$key); if($explode[0]){ $logfile = "./log/".urlencode($explode[0]).".cgi"; } $file = fopen("$logfile", 'w'); flock($file,LOCK_EX); fwrite($file, $value); flock($file,LOCK_UN); fclose($file); 解決法が分かる方、回答のほどよろしくお願いいたします。

    • ベストアンサー
    • PHP
  • phpである処理をすると数を1足して、ある処理をするとその数字から1引

    phpである処理をすると数を1足して、ある処理をするとその数字から1引くような事をしたいのですが、上手くいきません。(まれに数字にずれが生じてしまいます。) 1足していくもの $fp = fopen("./data/registry/buy.dat","r+"); $registry_count = fgets($fp,1024); if($registry_count == ""){ $registry_count = 0; } $registry_count++; flock($fp,LOCK_EX); fseek($fp,0); fputs($fp,$registry_count); flock($fp,LOCK_UN); fclose($fp); 1引いていくもの $fp = fopen("./data/registry/buy.dat","r+"); $registry_count = fgets($fp,1024); if($registry_count != "0"){ $registry_count--; } flock($fp,LOCK_EX); fseek($fp,0); ftruncate($fp,0); fputs($fp,$registry_count); flock($fp,LOCK_UN); fclose($fp); どなたかご教授ください。 よろしくお願いいたします。

    • ベストアンサー
    • PHP
  • 同じような処理を一つにまとめたい

    count.txt <?php $dis123=0; $dis001=0; $hoge01=0; ?> ___________ counter.php <?php $vote = $_GET[vote]; $fp = fopen("count.txt", "r+"); include("count.txt"); @flock($fp,LOCK_EX); //今現在(カウント前)の値を書き込む fputs($fp,"<?php \$dis123=$dis123; ?>\n"); fputs($fp,"<?php \$dis001=$dis001; ?>\n"); fputs($fp,"<?php \$hoge01=$hoge01; ?>\n"); //GETで得た情報からカウントした物に+1して書き込む if ($vote===dis123){ ++$dis123; fputs($fp,"<?php $$vote=$dis123; ?>\n"); } if ($vote===dis001){ ++$dis001; fputs($fp,"<?php $$vote=$dis001; ?>\n"); } if ($vote===hoge01){ ++$hoge01; fputs($fp,"<?php $$vote=$hoge01; ?>\n"); } flock($fp,LOCK_UN); fclose($fp); echo "dis123は".$dis123."点<br>"; echo "dis001は".$dis001."点<br>"; echo "hoge01は".$hoge01."点<br>"; ?> _________________________________ 処理: counter.php?vote=dis123ときたらif処理して$dis123に+1する ________________________ 今は三つだからまだ大丈夫ですが、これが増えてくると手間が多いです そこで上記の今現在の値の書き込みとIF処理の部分を代入など、なんらかの形で簡略化できませんでしょうか?大改編になっても結構です。 よろしくお願いします。 備考:PHP暦三日目です、ここまでなんだかんだがんばったと思う。

    • ベストアンサー
    • PHP
  • flockについて

    http://www.freespace.jp/phpstudy.php4 のサイト様を拝見したり、フリーで配布されているスクリプトを見ると、書き込むファイルに対して、 $fp = fopen('bbs.log', 'r+'); flock($fp, LOCK_EX); … とやっていると思うのですが、perl記述のcgiで掲示板を作成したときは、書き込むファイルとは別にロック用のファイルを用意し、(perl記述です) open(LOCK,"+<$lockfile"); flock(LOCK,2); open(IN,"$logfile"); .... close(IN,"$logfile"); open(OUT,"$logfile"); .... close(OUT,">$logfile"); としていました。(書き込むファイルが2つあったのでこのような方法をとってました) そこでphpでも同じ方法は使えるのでしょうか? $fp = fopen('bbs.log', 'r+'); flock($fp, LOCK_EX); … の方法を使おうと思っていたのですが、最初にログファイルを読み込むとき、 file("bbs.log"); という風にしているので、flockに記述すべきファイルハンドルが見当たりません。仮に取得できたとしても、file();の仕様からして内部にcloseが入ってそうなので、flockできたとしてもcloseで無効になってしまわないかが心配です。なのでこの場合はやはり別にログファイルを用意しないとできないということでしょうか。

    • ベストアンサー
    • PHP
  • PHPのアクセスカウンターのバグについてです!

    PHPを勉強しているものですが アクセスカウンターをネットで調べ自分なりに書いたのですが 日にちが変わるとトータル、今日、昨日が全く動かなくなります。 どこをどうすればいいのか教えていただけないでしょうか? お願いします。 $txt='counter.txt'; $fp=fopen($txt,'r+'); if($fp!==false){ if(flock($fp,LOCK_EX)){ $counter=fgets($fp);//トータル 今日 昨日 日付 $count=explode(' ',$counter); if(date('j') != $count[3]){ $count[3]=date('j'); $count[2]=$count[1]; $count[1]=0; } $count[0]++; $count[1]++; $counter=implode(' ',$count); rewind($fp); fputs($fp,$counter); flock($fp,LOCK_UN);} } fclose($fp); ちなみにバグはトータル→今日→昨日→日付の順です。 500 1 1 262625 のようになっていました。 よろしくです。

    • ベストアンサー
    • PHP