php 实现tailf
实现 PHP 的 tail -f 功能
在 PHP 中模拟 Linux 的 tail -f 命令功能,可以实时监控文件末尾的变化并输出新增内容。以下是几种实现方法:
方法一:使用 fseek 和循环
通过不断检查文件大小变化并读取新增内容实现:
function tailFile($filename, $delay = 1) {
$file = fopen($filename, "r");
fseek($file, 0, SEEK_END); // 初始定位到文件末尾
while (true) {
$currentSize = filesize($filename);
$currentPos = ftell($file);
if ($currentSize < $currentPos) {
// 文件被截断(如日志轮转),重新打开
fclose($file);
$file = fopen($filename, "r");
fseek($file, 0, SEEK_END);
} else {
// 读取新增内容
$newData = fread($file, $currentSize - $currentPos);
if ($newData !== false && $newData !== '') {
echo $newData;
flush();
}
}
sleep($delay); // 延迟避免高频检查
}
}
// 使用示例
tailFile("/var/log/example.log");
方法二:使用 inotify 扩展(Linux 系统)
需要安装 inotify PHP 扩展,效率更高:
function tailWithInotify($filename) {
$fd = inotify_init();
$watch = inotify_add_watch($fd, $filename, IN_MODIFY);
$file = fopen($filename, "r");
fseek($file, 0, SEEK_END);
while (true) {
$events = inotify_read($fd);
foreach ($events as $event) {
if ($event['mask'] & IN_MODIFY) {
$newData = fread($file, 8192); // 读取块大小
echo $newData;
flush();
}
}
}
inotify_rm_watch($fd, $watch);
fclose($fd);
}
方法三:通过系统命令调用
直接调用系统 tail -f 命令(需确保安全):

function tailViaSystem($filename) {
$handle = popen("tail -f " . escapeshellarg($filename) . " 2>&1", "r");
while (!feof($handle)) {
echo fread($handle, 8192);
flush();
}
pclose($handle);
}
注意事项
- 权限问题:确保 PHP 进程有权限读取目标文件。
- 性能影响:方法一的轮询方式在高并发场景可能影响性能。
- 文件轮转:日志文件可能被轮转(如
logrotate),需要处理文件被截断的情况。 - 内存管理:长时间运行的脚本需注意内存泄漏问题。
对于生产环境,推荐使用方法二(inotify)或方法三(系统命令),前者更高效,后者更简单但需考虑命令注入风险。






