17

I want to make movement such as the tail command with PHP, but how may watch append to the file?

2

6 Answers 6

24

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"); 
Sign up to request clarification or add additional context in comments.

7 Comments

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?
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.
I tried this code, but no success... the browser keeps loading... and no echoing..
@ihtus This code is not intended for browser, as it does not end (so no server response is generated or server timeout is reached).
@ihtus: you could flush it to browser
|
12
$handle = popen("tail -f /var/log/your_file.log 2>&1", 'r'); while(!feof($handle)) { $buffer = fgets($handle); echo "$buffer\n"; flush(); } pclose($handle); 

2 Comments

It crash apache server .. Do this only to me ?
Check your error logs for clues, but this should not be crashing your apache process.
5

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).

Comments

2
$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

Comments

2

Instead of polling filesize you regular checking the file modification time: filemtime

1 Comment

Both requires a stat() call underneath the surface, so it doesn't really matter.
0

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); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.