PHP は linux コマンド tail -f を実装します
今日、以前誰かが私に尋ねた質問を突然思い出しました。PHP を介して linux コマンド tail -f を実装する方法をここで分析して実装してみましょう。
これは非常に単純です。ファイルのサイズが変更されたかどうかをループで検出し、変更があればファイルの変更された部分を出力します。詳細な分析は次のとおりです。
初期ファイルが大きすぎる場合、またはコンテンツの変更が多すぎる場合
一度に多くのコンテンツを出力すると、はっきりと見えなくなる可能性があるため、コンテンツの長さがこのしきい値を超える場合は、ここでしきい値を8192に設定します。の場合、最後の 8192 バイトのみが出力されるため、広範囲のリフレッシュによって発生する視認性の問題は発生しません。
ファイルサイズの変化を検出する方法
この問題は、このプログラムの核心であり、成功できるかどうかは、パフォーマンスのこの部分に依存します。ここでの私の実装は次のとおりです:
ファイル ハンドル $fp を開きます。ここで注意すべき点は、このファイル ハンドルはプロセス全体で 1 回開いて 1 回閉じるだけでよいため、ループの外に配置する必要があります。
現在のファイルサイズfile_sizeとfile_size_newを0に初期化します。
file_size_new ファイル サイズはループ内で更新されます。PHP でファイル サイズを取得する前に、clearstatcache() 関数を実行してファイル ステータス キャッシュをクリアする必要があることに注意してください。そうしないと、ファイル サイズの取得に誤差が生じる可能性があります。
add_size = file_size_new - file_size を計算して、ファイル サイズが変更されたかどうかを確認し、変更がある場合は、ファイル ポインターを指定した位置に移動し、新しく追加されたコンテンツを出力し、file_size の値を new_file_size に更新します。
usleep(50000)、1/20 秒間スリープします。
コード実装
#!/usr/bin/env php <?php if(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公式マニュアルを確認したところ、この関数はオフセットポインタのタイプを示す3番目のパラメータも受け入れることができました。 、先頭からのオフセットは、現在位置からのオフセットを意味する SEEK_CUR に設定することもできるため、ここでは fseek($fp, $ignore_size, $ignore_size);
結果は次のとおりです