これをどのように表現すればよいかわからないので、入力してから編集し、出てくる質問に答えます..
現在、ローカル ネットワーク デバイス (PHP4 ベース) で、これを使用してライブ システム ログ ファイルを追跡しています: http://commavee.com/2007/04/13/ajax-logfile-tailer-viewer/
これはうまく機能し、1 秒ごとに外部ページ (logfile.php) をロードしますtail -n 100 logfile.log
。スクリプトはバッファリングを行わないため、画面に表示される結果はログ ファイルの最後の 100 行です。
logfile.php には以下が含まれます。
<? // logtail.php $cmd = "tail -10 /path/to/your/logs/some.log"; exec("$cmd 2>&1", $output);
foreach($output as $outputline) {
echo ("$outputline\n");
}
?>
この部分はうまく機能しています。
$outputline を新しいテキスト ファイルに書き込むように logfile.php ページを調整しました。fwrite($fp,$outputline."\n");
これは機能しますが、作成された新しいファイルの重複に問題があります。
明らかに、tail -n 100 が実行されるたびに結果が生成されます。次に実行すると、同じ行がいくつか生成される可能性があります。これが繰り返されるため、新しいテキスト ファイルに複数の行が重複してしまう可能性があります。
同一の一致がある可能性があるため、これから書き込もうとしている行を前の行と直接比較することはできません。
この100行の現在のブロックを前のブロックと比較して、一致しない行のみを書き込む方法はありますか..ブロックAとBに必要な同一の行が含まれるという問題が再び発生する可能性があります...
logfile.php を更新して、ログファイルで最後に取得した位置を記録し、そこから次の 100 行のみを読み取り、それらを新しいファイルに書き込むことは可能ですか?
ログ ファイルは最大 500 MB になる可能性があるため、毎回すべてを読みたくありません..
アドバイスや提案は大歓迎です..
ありがとう
更新 @ 16:30
私はこれを次のように使用して動作させました:
$file = "/logs/syst.log";
$handle = fopen($file, "r");
if(isset($_SESSION['ftell'])) {
clearstatcache();
fseek($handle, $_SESSION['ftell']);
while ($buffer = fgets($handle)) {
echo $buffer."<br/>";
@ob_flush(); @flush();
}
fclose($handle);
@$_SESSION['ftell'] = ftell($handle);
} else {
fseek($handle, -1024, SEEK_END);
fclose($handle);
@$_SESSION['ftell'] = ftell($handle);
}
これは機能しているように見えますが、最初にファイル全体をロードしてから更新のみをロードします。
最後の 50 行から開始して、更新だけを取得するにはどうすればよいですか?
ありがとう :)
UPDATE 04/06/2013 これは機能しますが、大きなファイルでは非常に遅くなります。
このコードを試してみましたが、高速に見えますが、中断したところから読み取るだけではありません。
function last_lines($path, $line_count, $block_size = 512){
$lines = array();
// we will always have a fragment of a non-complete line
// keep this in here till we have our next entire line.
$leftover = "";
$fh = fopen($path, 'r');
// go to the end of the file
fseek($fh, 0, SEEK_END);
do{
// need to know whether we can actually go back
// $block_size bytes
$can_read = $block_size;
if(ftell($fh) < $block_size){
$can_read = ftell($fh);
}
// go back as many bytes as we can
// read them to $data and then move the file pointer
// back to where we were.
fseek($fh, -$can_read, SEEK_CUR);
$data = fread($fh, $can_read);
$data .= $leftover;
fseek($fh, -$can_read, SEEK_CUR);
// split lines by \n. Then reverse them,
// now the last line is most likely not a complete
// line which is why we do not directly add it, but
// append it to the data read the next time.
$split_data = array_reverse(explode("\n", $data));
$new_lines = array_slice($split_data, 0, -1);
$lines = array_merge($lines, $new_lines);
$leftover = $split_data[count($split_data) - 1];
}
while(count($lines) < $line_count && ftell($fh) != 0);
if(ftell($fh) == 0){
$lines[] = $leftover;
}
fclose($fh);
// Usually, we will read too many lines, correct that here.
return array_slice($lines, 0, $line_count);
}
最後の既知の位置から読み取るように、これを修正する方法はありますか..?
ありがとう