我想读取一直被写入的日志文件。它与应用程序位于同一服务器上。问题是文件被写入每隔几秒钟,我基本上想要tail
实时应用程序中的文件。
这可能吗?
答案 0 :(得分:22)
你需要循环睡眠:
$file='/home/user/youfile.txt';
$lastpos = 0;
while (true) {
usleep(300000); //0.3 s
clearstatcache(false, $file);
$len = filesize($file);
if ($len < $lastpos) {
//file deleted or reset
$lastpos = $len;
}
elseif ($len > $lastpos) {
$f = fopen($file, "rb");
if ($f === false)
die();
fseek($f, $lastpos);
while (!feof($f)) {
$buffer = fread($f, 4096);
echo $buffer;
flush();
}
$lastpos = ftell($f);
fclose($f);
}
}
(已测试..有效)
答案 1 :(得分:2)
是的,您需要在循环中睡一些时间,但不必重新打开文件。我只是在寻找类似的问题。我想读取一个自上次读取以来可能已更改的文件。
问题在于资源已到达文件(EOF
)的末尾。并且不会继续阅读。解决方案是使用fseek($fh, ftell($fh))
重置指针。
一个等待在文本文件中输入的完整程序可能看起来像这样:
<?php
$fh = fopen('/var/log/system', 'r');
while (true) {
$line = fgets($fh);
if ($line !== false) {
// show the line or send it via email or to a websocket..
} else {
// sleep for 0.1 seconds (or more?)
usleep(0.1 * 1000000);
fseek($fh, ftell($fh));
}
}
答案 2 :(得分:0)
您可以在未使用时关闭文件句柄(一旦写入一部分数据)。或者您可以使用缓冲区来存储数据并仅在数据已满时将其放入文件中。这样你就不会一直打开文件。
如果你希望在写入文件后立即将所有内容写入文件,你可能需要扩展代码,编写数据,以便输出到其他地方(屏幕,一些变量,其他档案......)
答案 3 :(得分:0)
例如:
$log_file = '/tmp/test/log_file.log';
$f = fopen($log_file, 'a+');
$fr = fopen($log_file, 'r' );
for ( $i = 1; $i < 10; $i++ )
{
fprintf($f, "Line: %u\n", $i);
sleep(2);
echo fread($fr, 1024) . "\n";
}
fclose($fr);
fclose($f);
//Or if you want use tail
$f = fopen($log_file, 'a+');
for ( $i = 1; $i < 10; $i++ )
{
fprintf($f, "Line: %u\n", $i);
sleep(2);
$result = array();
exec( 'tail -n 1 ' . $log_file, $result );
echo "\n".$result[0];
}
fclose($f);
答案 4 :(得分:-1)
只是一个想法..
你有没有想过使用* nix tail命令?从php执行命令(使用将返回一定数量行的param)并在php脚本中处理结果。