ツッコミもらってるのに反応遅くて申し訳ない。
えーっと、さとしすのツッコミを引用しますが...
○seek (IN,0,1); で、end-of-fileエラーをリセットできるとかなり幸せ。(cf.プログラミングPerl 関数seek解説)
○use FileHandle;.... ; OUT->autoflush(1);で、バッファ無しで即時追加。
○真似して、 last if ($inode != (stat($infile))[1]); とやって、ログローテートしたときに、openし直すようにしてみたけどうまく行かなかったんで、cronで一分後に再起動。ダサいのが残ってしまいました。
一つ目の○は、通常 eof 検出までログを読み続け、end-of-file エラーを検出した時点で、seek(IN,0,1)を発行してエラーをリセットし... この後はどうしましょう。通常こういったパターンだと、1秒とかのsleep後に、再度読み込みを行い、データが有れば処理するし、無ければ同様にsleepして、再度読み込みってのを続けると思いますが...
私が作った奴は、最初にどこまで読めるか見ている($rec_ptr=tell(IN);)ので、end-of-file を検出すること無いハズで、仮に検出したとしたら、それはバグってことになります。
二つ目の○は、出力ファイルをオープンしっぱなしの場合は、そういった対処が必要でしょうね。perl の場合良く使われるコーディングパターンとしては、select(OUT); $|=1; select(STDOUT); ってヤツですね。
三つ目の○は何とかしたいですね。logrotate の方式にもよりますが、copytruncate だとしたらうまく動かない可能性大です。真っ当なsyslogのように、ファイル自体を切替えてくれる場合は i-node 番号が変わることでファイルが切り替わったことを知ることができますが、copytruncate の場合は、中身を別ファイルにコピーして、コピーが終わったらファイル自体を0バイトに切り詰めるだけなので、i-node 番号が変わりません。そんなわけで、私が作ったスクリプトでは、ファイルサイズを見るように... してたつもりですが、これじゃダメですね(^^;
さて、どうするかな... とりあえずstat取った後、$rec_ptrがファイルサイズより大きかったら、$rec_ptrをゼロに設定してみますかね。
1)for(;;){while(<IN>){.;..;..;}sleep 1;seek IN,0,1;}で、最終行まで読んで処理して、他プロセスでファイルが伸びたらそれも処理する、という動作ができるそうです。ファイルポインタ管理はPerlにおまかせということで。(Cライブラリの「標準度」によっては不可の事もあるらしい)<br>2)標準モジュールあるからselectよりもこっちを使ってとPerlの一番偉い人は言っているらしい(下位互換性気になるなら不可)<br>3)ログの安全性から見ると「コピーしてから0にする」ほうが良いですね。そうか、inode変わらないのか。サイズでみるという事は、for(;;){open IN $infile;$size=(stat(IN))[7];for(;;){...;last if($size > (stat($infile))[7];}}なのかな?