I want to make movement such as the tail command with PHP, but how may watch append to the file?
-
2http://code.google.com/p/php-tail/ – Peeter Jan 31 '11 at 14:08
-
Available on Packagist: https://packagist.org/packages/icyapril/tail – mjsa Apr 23 '17 at 07:44
6 Answers
I don't believe that there's some magical way to do it. You just have to continuously poll the file size and output any new data. This is actually quite easy, and the only real thing to watch out for is that file sizes and other stat data is cached in php. The solution to this is to call clearstatcache()
before outputting any data.
Here's a quick sample, that doesn't include any error handling:
function follow($file)
{
$size = 0;
while (true) {
clearstatcache();
$currentSize = filesize($file);
if ($size == $currentSize) {
usleep(100);
continue;
}
$fh = fopen($file, "r");
fseek($fh, $size);
while ($d = fgets($fh)) {
echo $d;
}
fclose($fh);
$size = $currentSize;
}
}
follow("file.txt");

- 39,840
- 10
- 78
- 97
-
Hi, Your solution seems to be burning a lot of CPU (+-40% on my test config). Are there any pointers to a more efficient way of watching folders? – Coyote Jun 25 '12 at 10:54
-
1`usleep(100)` is sleeping for 100 millionths of a second, or for 0.0001 seconds. Increase this to `usleep(10000)` (0.01s) for lower CPU usage unless you need extremely low latency. `usleep(2000000)` or `sleep(2)` (2s) for something that you just want reasonably fresh when you glance at it. – ReactiveRaven Jan 10 '13 at 11:00
-
I tried this code, but no success... the browser keeps loading... and no echoing.. – ihtus Oct 25 '13 at 17:05
-
@ihtus This code is not intended for browser, as it does not end (so no server response is generated or server timeout is reached). – SteveB Apr 18 '14 at 09:18
-
@ihtus: you could [flush](http://php.net/manual/en/function.flush.php) it to browser – machineaddict Nov 27 '14 at 08:44
-
@EmilH: If I use this code, then I might land up creating a deadlock. As some other process might be writing to this file at the same time. – Veer Shrivastav Aug 11 '16 at 06:41
-
$handle = popen("tail -f /var/log/your_file.log 2>&1", 'r');
while(!feof($handle)) {
$buffer = fgets($handle);
echo "$buffer\n";
flush();
}
pclose($handle);

- 1,608
- 15
- 17
-
-
Check your error logs for clues, but this should not be crashing your apache process. – Glenn Plas Feb 09 '16 at 11:57
Checkout php-tail on Google code. It's a 2 file implementation with PHP and Javascript and it has very little overhead in my testing.
It even supports filtering with a grep keyword (useful for ffmpeg which spits out frame rate etc every second).

- 4,301
- 6
- 37
- 61
$handler = fopen('somefile.txt', 'r');
// move you at the end of file
fseek($handler, filesize( ));
// move you at the begining of file
fseek($handler, 0);
And probably you will want to consider a use of stream_get_line

- 40,769
- 9
- 59
- 81
Instead of polling filesize you regular checking the file modification time: filemtime

- 61,720
- 15
- 75
- 100
-
3Both requires a stat() call underneath the surface, so it doesn't really matter. – Emil H Jul 09 '09 at 10:06
Below is what I adapted from above. Call it periodically with an ajax call and append to your 'holder' (textarea)... Hope this helps... thank you to all of you who contribute to stackoverflow and other such forums!
/* Used by the programming module to output debug.txt */
session_start();
$_SESSION['tailSize'] = filesize("./debugLog.txt");
if($_SESSION['tailPrevSize'] == '' || $_SESSION['tailPrevSize'] > $_SESSION['tailSize'])
{
$_SESSION['tailPrevSize'] = $_SESSION['tailSize'];
}
$tailDiff = $_SESSION['tailSize'] - $_SESSION['tailPrevSize'];
$_SESSION['tailPrevSize'] = $_SESSION['tailSize'];
/* Include your own security checks (valid user, etc) if required here */
if(!$valid_user) {
echo "Invalid system mode for this page.";
}
$handle = popen("tail -c ".$tailDiff." ./debugLog.txt 2>&1", 'r');
while(!feof($handle)) {
$buffer = fgets($handle);
echo "$buffer";
flush();
}
pclose($handle);

- 11
- 1