I want to create a script that parses or makes sense of apache's error log to see what the most recent error was. 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:
- Firstly, your PHP user may not have access to Apache's log files.
- Secondly, PHP and Apache aren't going to tell you where said log file is,
- Lastly, Apache log files can get quite large.
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
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 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. 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
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>";
}
?>
Have you tried biterScripting ? I am a system admin and I have been using to parse logs. It is univx style scripting. biterScripting.com -> Free download.
© 2022 - 2024 — McMap. All rights reserved.