简体   繁体   English

如何在 PHP 中解析 A​​pache 的错误日志?

[英]How can I parse Apache's error log in PHP?

I want to create a script that parses or makes sense of apache's error log to see what the most recent error was.我想创建一个脚本来解析或理解 apache 的错误日志,以查看最近的错误是什么。 I was wondering if anyone out there has something that does this or has any ideas where to start?我想知道是否有人在那里做这件事或有任何想法从哪里开始?

There are a few things to consider first: 首先要考虑以下几点:

  1. Firstly, your PHP user may not have access to Apache's log files. 首先,您的PHP用户可能无法访问Apache的日志文件。
  2. Secondly, PHP and Apache aren't going to tell you where said log file is, 其次,PHP和Apache不会告诉你日志文件在哪里,
  3. Lastly, Apache log files can get quite large. 最后,Apache日志文件可能会变得非常大。

However, if none of these apply, you can use the normal file reading commands to do it. 但是,如果这些都不适用,则可以使用普通文件读取命令来执行此操作。 The easiest way to get the last error is 获取最后一个错误的最简单方法是

$contents = @file('/path/to/error.log', FILE_SKIP_EMPTY_LINES);
if (is_array($contents)) {
    echo end($contents);
}
unset($contents);

There's probably a better way of doing this that doesn't oink up memory, but I'll leave that as an exercise for the reader. 这可能是一种更好的方法,不会记忆,但我会把它作为读者的练习。

One last comment: PHP also has an ini setting to redirect PHP errors to a log file: error_log = /path/to/error.log 最后一条评论:PHP还有一个将PHP错误重定向到日志文件的ini设置: error_log = /path/to/error.log

You can set this in httpd.conf or in an .htaccess file (if you have access to one) using the php_flag notation: 你可以使用php_flag表示法在httpd.conf或.htaccess文件中设置它(如果你有访问权限):

php_flag error_log /web/mysite/logs/error.log

for anyone else looking for a sample script, i threw something together, it's got the basics: 对于其他寻找样本脚本的人,我把东西放在一起,它有基础知识:

<?php
exec('tail /usr/local/apache/logs/error_log', $output);
?>
<Table border="1">
    <tr>
        <th>Date</th>
        <th>Type</th>
        <th>Client</th>
        <th>Message</th>
    </tr>
<?
    foreach($output as $line) {
        // sample line: [Wed Oct 01 15:07:23 2008] [error] [client 76.246.51.127] PHP 99. Debugger->handleError() /home/gsmcms/public_html/central/cake/libs/debugger.php:0
        preg_match('~^\[(.*?)\]~', $line, $date);
        if(empty($date[1])) {
            continue;
        }
        preg_match('~\] \[([a-z]*?)\] \[~', $line, $type);
        preg_match('~\] \[client ([0-9\.]*)\]~', $line, $client);
        preg_match('~\] (.*)$~', $line, $message);
        ?>
    <tr>
        <td><?=$date[1]?></td>
        <td><?=$type[1]?></td>
        <td><?=$client[1]?></td>
        <td><?=$message[1]?></td>
    </tr>
        <?
    }
?>
</table>

there are piles of php scripts that do this, just do a google search for examples. 有成堆的PHP脚本执行此操作,只需谷歌搜索示例。 if you want to roll your own, it's nothing more complex than reading any other file. 如果你想自己动手,那就没有比阅读任何其他文件更复杂了。 just make sure you know the location of your logfiles (defined in the httpd.conf file) and the format your log files are in. the format is also defined in httpd.conf 只需确保您知道日志文件的位置(在httpd.conf文件中定义)和日志文件所在的格式。格式也在httpd.conf中定义

Here's a small-ish class that makes it easy to read a number of characters from the back of a large file w/o overloading memory. 这是一个小型的类,可以很容易地从大文件的后面读取多个字符,而不会使内存过载。 The test setting lets you see it in action cannibalizing itself. 通过测试设置,您可以看到它在行动中蚕食自己。

BigFile.php
<?php
$run_test = true;
$test_file = 'BigFile.php';

class BigFile
{
private $file_handle;

/**
 * 
 * Load the file from a filepath 
 * @param string $path_to_file
 * @throws Exception if path cannot be read from
 */
public function __construct( $path_to_log )
{
    if( is_readable($path_to_log) )
    {
        $this->file_handle = fopen( $path_to_log, 'r');
    }
    else
    {
        throw new Exception("The file path to the file is not valid");
    } 
}

/**
 * 
 * 'Finish your breakfast' - Jay Z's homme Strict
 */
public function __destruct()
{
    fclose($this->file_handle); 
}

/**
 * 
 * Returns a number of characters from the end of a file w/o loading the entire file into memory
 * @param integer $number_of_characters_to_get
 * @return string $characters
 */
public function getFromEnd( $number_of_characters_to_get )
{
    $offset = -1*$number_of_characters_to_get;
    $text = "";

    fseek( $this->file_handle, $offset , SEEK_END);

    while(!feof($this->file_handle))
    {
        $text .= fgets($this->file_handle);
    }

    return $text;
}
}

if( $run_test )
{
$number_of_characters_to_get =  100000; 
$bf = new BigFile($test_file);
$text = $bf->getFromEnd( $number_of_characters_to_get );
echo "$test_file has the following $number_of_characters_to_get characters at the end: 
    <br/> <pre>$text</pre>";
}

?> 

adm group has access of to view logs in linux system to access the log from apache we have to add www-data user to adm group and restart the apache so all the changes will update adm组有权查看linux系统中的日志从apache访问日志我们要将www-data用户添加到adm组并重新启动apache所以所有的更改都会更新

$ sudo usermod -G adm www-data
$ sudo service apache2 restart

<?php
 exec('tail /var/log/apache2/error_log', $output);
?>
<Table border="1">
<tr>
    <th>Date</th>
    <th>Type</th>
    <th>Client</th>
    <th>Message</th>
</tr>
<?php
foreach($output as $line) {
    // sample line: [Mon Apr 01 07:23:14.217466 2019] [autoindex:error] [pid 19261] [client 114.143.38.172:55801] AH01276:PHP 99. Debugger->handleError() 
   /home/gsmcms/public_html/central/cake/libs/debugger.php:0

    preg_match('~^\[(.*?)\]~', $line, $date);
    if(empty($date[1])) {
        continue;
    }
    preg_match('~\] \[([a-z:]*?)\] \[~', $line, $type);
    preg_match('~\] \[client ([0-9\.:]*)\]~', $line, $client);
    preg_match('~\] (.*)$~', $line, $message);
    ?>
<tr>
    <td><?=$date[1]?></td>
    <td><?=$type[1]?></td>
    <td><?=$client[1]?></td>
    <td><?=$message[1]?></td>
</tr>
    <?
}
?>

Have you tried biterScripting ? 你试过biterScripting吗? I am a system admin and I have been using to parse logs. 我是系统管理员,我一直用来解析日志。 It is univx style scripting. 它是univx风格的脚本。 biterScripting.com -> Free download. biterScripting.com - >免费下载。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM