今天突然想到之前有人问过我的一个问题,如何通过PHP实现linux中的命令 tail -f ,这里就来分析实现下。
这个想一想也挺简单,通过一个循环检测文件,看文件的大小是否有变化,如果有变化,输出文件变化的部分,当然了这里面会有好多的细节,这里具体分析下。
这个时候一下输出好多内容可能看不清,因此我这里设置了一个阈值 8192 ,当内容长度超过这个阈值的时候,只输出最后面的 8192 个字节,这样就不会出现大面积的刷新导致看不清的问题。
这个问题是这个程序的核心,能不能成功,性能的好坏就靠这部分了。我在这里的实现是下面这样:
#!/usr/bin/env php <?phpif(2 != count($argv)){ fwrite( STDERR, "调用格式错误!使用格式 ./tail filename".PHP_EOL ); return 1;}$file_name = $argv[1];define("MAX_SHOW", 8192);$file_size = 0;$file_size_new = 0;$add_size = 0;$ignore_size = 0;$fp = fopen($file_name, "r");while(1){ clearstatcache(); $file_size_new = filesize($file_name); $add_size = $file_size_new - $file_size; if($add_size > 0){ if($add_size > MAX_SHOW){ $ignore_size = $add_size - MAX_SHOW; $add_size = MAX_SHOW; fseek($fp, $file_size + $ignore_size); } fwrite( STDOUT, fread($fp, $add_size) ); $file_size = $file_size_new; } usleep(50000);}fclose($fp);
代码实现这里第一行的 #!/usr/bin/env php 是告诉可执行文件,可执行文件 php 在系统 PATH 中查找,这样的好处就是移植性好。
2016-02-22 11:28:51改进
查了PHP官方手册, fseek 函数这里可以改进改进,这个函数还接受第三个参数,表示偏移指针的类型,默认是 SEEK_SET ,从开始偏移,还可以设置为 SEEK_CUR ,表示从当前位置偏移,因此这里改为 fseek($fp, $ignore_size, $ignore_size);