Forum Moderators: coopster

Message Too Old, No Replies

displaying the last 20 lines from a logfile

         

jatar_k

5:57 pm on Sep 29, 2006 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



I am wanted to read the last lines of some logs because I didn't want to use up bandwidth viewing the whole thing all the time.

I am now using this, just hacked it together using some stuff that was lying around.

params passed are
$_GET['logname'] = this is generated by a read dir type script and of the form filename.ext
$_GET['lines'] = number of lines you want to see

$logname = $_GET['logname']; 
$logdir = '/path/to/logfiles/';
$buffer = '';
$lines = false;
if (isset($_GET['lines'])) $lines = $_GET['lines'];
// check to see if they want the full log or just the last x lines
if (!$lines) {
$buffer = file_get_contents($logdir . $logname);
echo '<textarea cols="120" rows="40" name="logdata" wrap="off">';
echo $buffer;
echo '</textarea>';
} else {
$fp = fopen($logdir . $logname,'r');
if ($fp) {
$linesarr = array();
while (!feof($fp)) {
$buffer = fgets($fp);
$linesarr[] = $buffer;
if (count($linesarr) > $lines + 1) array_shift($linesarr);
}
fclose($fp);
// now display what is in the array
echo '<textarea cols="150" rows="21" name="logdata" wrap="off">';
$counter = 0;
while (isset($linesarr[$counter])) {
echo $linesarr[$counter];
$counter++;
}
echo '</textarea>';
} else {
echo '<p>',$logdir,$logname,' could not be opened.';
die();
}
}

there is no input/variable verification on this as it is only used by me and there are 3 layers of security making sure that it's me, IP being one of them. I'm just playing mostly.

I wanted to limit the amount of data I was keeping in memory, hence the array_shift.

I like it displayed in a textarea so it doesn't wrap

can someone think of something more interesting?

ahmedtheking

6:23 pm on Sep 29, 2006 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Why not:

$file = file("path/to/log.txt");
$last20lines = array_chunk($file,20);
$last20lines = implode("\n",$last20lines);

jatar_k

6:42 pm on Sep 29, 2006 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



the only problem being then I would have to read the whole file into mem

being that it is a custom log file and I don't plan on rotating it much, the size may get large

jezra

6:48 pm on Sep 29, 2006 (gmt 0)

10+ Year Member



If your script has access to the "tail" command, you could try something like this.

$logname = $_GET['logname'];
$logdir = '/path/to/logfiles/';
$file_abs_path = $logdir . $logname;
$buffer = '';
$lines = false;
if (isset($_GET['lines'])) $lines = $_GET['lines'];
// does the file exist?
if( file_exists($file_abs_path))
{
// check to see if they want the full log or just the last x lines
if (!$lines) {
$buffer = file_get_contents($file_abs_path);
} else {
$commmand = "tail -$lines $file_abs_path";
$buffer = exec($command);
}
echo '<textarea cols="120" rows="40" name="logdata" wrap="off">';
echo $log_output;
echo '</textarea>';
}else {
echo '<p>',$logdir,$logname,' could not be opened.';
die();
}

Since this code requires some non-PHP functionality, I'd call myself a cheater.

jatar_k

6:53 pm on Sep 29, 2006 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



actually I did think about tail but figured I would do it without using exec, which is what I was thinking, a tail solution simply in php

I haven't even tried using exec, passthru etc with this account yet

jezra

7:28 pm on Sep 29, 2006 (gmt 0)

10+ Year Member



since the log file could get quite large, it makes sense to start reading from the end of the file.

How about reading the file, character by character, in reverse, for x number of new lines?

coopster

7:48 pm on Sep 29, 2006 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Could you use fseek [php.net] with the optional SEEK_END argument to set the position to end-of-file plus offset bytes? Grab that chunk of data, parse it on the newlines to build your array. Of course, your offset bytes would have to be large enough to attain the approximate lines you would like. Not sure if this would work, just throwing it out there ...

jatar_k

9:11 pm on Sep 29, 2006 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



I thought about exactly that coop

I figured I could decide that X number of bytes is always more than you want and keeps the mem usage down

jezra, that was my initial plan but for some reason I didn't do that, there was a reason, I just can't remember what it was

I also know that the way I did it will slowly take longer and longer as the file gets larger, I am a little interested to see at what point it starts lagging. Though I am also way too lazy to test it. Guess I'll just let it run and see what happens. :)

like I said, this is for me only so it doesn't really matter

I would be interested if anyone else can think of anything interesting.

reading large text/log files is useful and quite a bit of fun