php 实现tailf
实现 PHP 的 tail -f 功能
PHP 可以通过文件操作和循环实现类似 Linux tail -f 的功能,实时监控文件末尾的新增内容。
基本实现方法
使用 fopen、fseek 和循环读取文件末尾内容:
$file = 'path/to/your/file.log';
$handle = fopen($file, 'r');
// 定位到文件末尾
fseek($handle, 0, SEEK_END);
while (true) {
// 检查文件是否被修改
clearstatcache();
$currentSize = filesize($file);
if ($currentSize > ftell($handle)) {
// 读取新增内容
$data = fread($handle, $currentSize - ftell($handle));
echo $data;
flush();
}
usleep(100000); // 暂停0.1秒
}
优化版本
添加文件旋转检查和错误处理:
function tail($file) {
$handle = fopen($file, 'r');
$lastPos = 0;
$fileInode = fileinode($file);
while (true) {
clearstatcache();
$currentInode = fileinode($file);
// 检查文件是否被旋转
if ($currentInode != $fileInode) {
fclose($handle);
$handle = fopen($file, 'r');
$fileInode = $currentInode;
$lastPos = 0;
}
$currentSize = filesize($file);
if ($currentSize < $lastPos) {
// 文件被截断
$lastPos = 0;
}
if ($currentSize > $lastPos) {
fseek($handle, $lastPos);
while (!feof($handle)) {
$line = fgets($handle);
if ($line !== false) {
echo $line;
flush();
}
}
$lastPos = ftell($handle);
}
usleep(100000);
}
}
tail('path/to/your/file.log');
使用 inotify 扩展(更高效)
如果服务器支持 inotify 扩展,可以实现更高效的监控:
if (!extension_loaded('inotify')) {
die('inotify extension not loaded');
}
$file = 'path/to/your/file.log';
$inotify = inotify_init();
$watch = inotify_add_watch($inotify, $file, IN_MODIFY);
$fp = fopen($file, 'r');
fseek($fp, 0, SEEK_END);
while (true) {
$events = inotify_read($inotify);
if ($events) {
$data = fread($fp, 8192);
echo $data;
flush();
}
usleep(100000);
}
注意事项
- 脚本会无限运行,需要手动终止
- 确保 PHP 有权限读取目标文件
- 在生产环境中使用时,应考虑添加超时和错误处理机制
- 对于大文件,可能需要调整读取缓冲区大小
- 在 Web 环境中使用时,需要确保输出缓冲和刷新机制正常工作







