在PHP中滚动日志文件

3
我希望使用PHP编写/读取一个滚动日志文件,仅存储/读取最新的约300行记录,旧记录会被丢弃。我不确定最有效的方法是什么-它需要快速工作,因为它记录高流量网站的页面访问量。
另一个PHP脚本将定期读取日志文件并使用数据进行计算。由于有很多PHP文件函数,我不知道从哪里开始!
我认为我的托管环境没有访问类似“tail”或“awk”的命令,因此更喜欢纯PHP解决方案。非常感谢您的帮助!

你考虑过使用数据库吗?或者除了你的 PHP 脚本之外,日志文件还需要被其他人访问吗? - Decent Dabbler
1
@fireeyedboy 我认为文件写入比数据库更快,一些快速的研究也证实了这一点。我只是想要数据输入和输出,所以我认为使用数据库有些过度。 - Tak
你可能是对的。 - Decent Dabbler
1
你有什么问题?从我所看到的来看,这只是一个“替我做”的帖子...而我们这里不会这样做。 - Lightness Races in Orbit
6个回答

0
你可以使用fopen: http://us3.php.net/manual/zh/function.fopen.php
$mode = 'a+'; // opens the file with read/write access and sets the pointer to the end of the file
$handle = fopen ($filename, $mode);

接下来,您将文件读入数组中,并且去掉除最后300行以外的所有内容。

如果您真的只想保持文件大小在一定范围内(您说过大约300行),那么可以使用 fseek http://us3.php.net/manual/en/function.fseek.php 函数(摘自手册):

<?php

$fp = fopen('somefile.txt', 'r');

// read some data
$data = fgets($fp, 4096);

// move back to the beginning of the file
// same as rewind($fp);
fseek($fp, 0);

?>

0

为了进行性能比较,您需要进行一些基准测试,但这里有一种可能的方法:

<?php
function writeToLog($file, $str, $maxLines = 300) {
    $linesToWrite = explode("\n", $str);
    $numLinesToWrite = count($linesToWrite);
    $logLines = explode("\n", file_get_contents($file));
    array_splice($logLines,
                 $maxLines - $numLinesToWrite,
                 $numLinesToWrite,
                 $linesToWrite);
    file_put_contents($file, implode("\n", $logLines));
}

0

对于这个的性能我也不确定,但是这是我的看法:

// read lines in file as array
$lines = file( 'log.log', FILE_IGNORE_NEW_LINES );

// log file equal to or larger than 300 lines?
if( count( $lines ) >= 300 )
{
    // remove everything from line 0 to 299 from the end
    // in other words keep last 299 lines
    array_splice( $lines, 0, -299 );
}
// append a new line of data
$lines[] = 'Test data ' . time() . "\n";

// put the lines back, first imploding the lines array with a newline char
file_put_contents( 'log.log', implode( "\n", $lines ) );

0

PHP函数用于此操作。确保日志可写。如果不存在,则创建日志:

// keeps log_file <= max_log_lines lines
function logTruncated($report, $log_file, $max_log_lines = 1000)
{
  if (!$report || !$log_file)
    return;
  if (!touch($log_file))
    die('Cant write log: '.$log_file);
  $lines = array_merge(file($log_file), preg_split('/\r?\n/', $report));
  $lines = array_slice($lines, -1 * $max_log_lines);
  file_put_contents($log_file, implode("\n", $lines));
}

0

它只是检查日志文件是否已经存在,以及如果其大于最大大小(我的代码中为4MB),则会读取它,删除一些文本并添加新文本,以便将大小保持在最大大小内。

$text = "Your text to log";
//if file exists and it's bigger than 4Mb then remove some text at the beginning to limit size
$log_file = __DIR__ . DIRECTORY_SEPARATOR . 'LOGS' . 'log.txt';
    if(file_exists($log_file)){
        clearstatcache();
        $size = filesize($log_file);
        if($size >= 4194304){
            $chunk = file_get_contents($log_file, FALSE, NULL, -(4194304 - strlen($text)));
            $text = $chunk . $text;
            $mode = 0;  //overwrite
        } else $mode = FILE_APPEND;
    }
    $file_exc = file_put_contents($log_file, $text . PHP_EOL , $mode | LOCK_EX);

请在您的答案中添加一些描述。 - William Baker Morrison

0

追加行并重命名已满文件

有时候最好的解决方案是稍微调整一下需求。

与其跳过许多环节来解析和修改单个日志文件,不如将每个新事件都追加到日志文件中,并在达到大小限制时滚动该文件。

function logEvent($line) {
   $maxLogFileSize =  24000;  //24K (about 300 lines)
   $logFilename =     "events.log";          //latest events
   $archiveFilename = "events-archive.log";  //older events
   if (filesize($logFilename) > $maxLogFileSize)
      rename($logFilename, $archiveFilename);
   file_put_contents($logFilename, $line . PHP_EOL, FILE_APPEND);
   }

通过将日志文件滚动到归档日志文件中,您可以实现所有目标,并且还能够:
  1. 简化代码
  2. 提高性能
  3. 减少文件损坏的风险

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接