December 3, 2010
So I’m working on a little admin interface and I decided to tail some logs. It’s in PHP and Google came up with some stuff, but they were all a bit finickey and not well documented. So I wrote my own!
Here’s the basic concept:
- Open File
- Seek To End
- Loop:
- Seek Back By Chunk Size
- Read Chunk
- Count Newlines
- Stash In Buffer
- Break If Enough Newlines Total
- Trim Extra Line & Cruft
- Done!
Here’s the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
function tail ( $file, $lines, $max_chunk_size = 4096 ) { // We actually want to look for +1 newline so we can get the whole first line $rows = $lines + 1; // Open up the file $fh = fopen( $file, 'r' ); // Go to the end fseek( $fh, 0, SEEK_END ); $position = ftell( $fh ); $buffer = ''; $found_newlines = 0; $break = false; while( ! $break ) { // If we are at the start then we are done. if( $position <= 0 ) { break; } // We can't seek past the 0 position obviously, so figure out a good chunk size $chunk_size = ( $max_chunk_size > $position ) ? $position : $max_chunk_size; // Okay, now seek there and read the chunk $position -= $chunk_size; fseek( $fh, $position ); $chunk = fread( $fh, $chunk_size ); // See if there are any newlines in this chunk, count them if there are if( false != strpos( $chunk, "\n" ) ) { if( substr( $chunk, -1 ) == "\n" ) { ++$found_newlines; } $found_newlines += count( explode( "\n", $chunk ) ); } // Have we exceeded our desired rows? if( $found_newlines > $rows ) { $break = true; } // Prepend $buffer = $chunk . $buffer; } // Now extract only the lines we requested $buffer = explode( "\n", $buffer ); return implode( "\n", array_slice( $buffer, count( $buffer ) - $lines ) ); } |
You can give it a try on some junk data here: http://static.velvetcache.org/pages/2010/12/03/tail-in-php/
Related posts:
There is no comment for this article.


