3

私はPerlを使用して、任意の時点で切り捨てられる可能性のあるログファイルを読み取ります。これが発生した場合、最初からファイルの読み取りを再開したいのですが、デフォルトのPerlの動作は、ファイルポインターが追いつくまで待機するようです。たとえば、次のコマンドを実行すると、次のようになります。

perl -e 'open FILE, "test"; while (1) { $line = <FILE>; print "$line"; }'

そして、次のことを行います。

for i in 1 2 3; do echo $i >> test; done
:>test
for i in 4 5 6 7; do echo $i >> test; done

私が得る出力は次のとおりです。

1
2
3
7

しかし、同じことをする場合は、Perlコードを次のように置き換えます。

tail -f test

次に(stderrへのテール出力を無視して)必要な出力を取得します。つまり、次のようになります。

1
2
3
4
5
6
7

もちろん、ライン自体に何らかの処理を加えたいので、テールだけを使用することはできません。私が持っていた1つの考えは、2つを組み合わせることでした。

tail -f test | perl -e 'while (1) { $line = <STDIN>; print "$line"; }'

これは私のLinux開発マシンでは動作しますが、残念ながらSolarisターゲットプラットフォームでは動作しません。

何か案は?

要求に応じて、File::Tailの使用例は次のとおりです。

perl -e 'use File::Tail; $file = File::Tail->new("test"); while (defined($line=$file->read)) { print "$line"; }'

次に、前と同じようにデータをテストに入力すると、得られる出力は次のようになります。

7

これは明らかに望まれることではありません。File::Tailが次のように待機するmaxintervalを調整しようとしました。

perl -e 'use File::Tail; $file = File::Tail->new(name => "test", maxinterval => 1); while (defined($line=$file->read)) { print "$line"; }'

ただし、その場合は、次のように、テストファイルへのデータの入力が速すぎます。

for i in 1 2 3; do echo $i >> test; done; :>test; for i in 4 5 6 7; do echo $i >> test; done

結果は次のようになります。

4
5
6
7

残念ながら、これは私たちの(非常に忙しい)アプリケーションにとって現実的なシナリオです。比較のために、Linuxテールはその種のデータ入力速度を適切に処理しているように見えるので、それができることはかなり明らかです(公平ではありますが、Perlではないかもしれません...?)

4

2 に答える 2

2

Linuxtailコマンドは、inotifyメカニズムを使用して、更新のためにファイルを繰り返しポーリングすることなく、ファイルへの変更を監視します。これにより、ファイルの変更に迅速かつ確実に対応できます。

Perlで同様の機能を実装するには、CPANのLinux::Inotify2モジュールを使用できます。残念ながら、名前が示すように、このモジュールはLinuxでのみ機能するため、スクリプトをSolarisに移植するのに役立ちません。

代わりに、SGI::FAMモジュールでFAMを使用できる場合があります。ネイティブのファイル変更通知メカニズムが利用できない場合でも、内部的にポーリングにフォールバックする可能性がありますが、少なくとも、ファイルポーリングの適切でテスト済みの実装を提供する必要があります。

于 2013-03-27T14:28:32.267 に答える
1

tailPerlでエミュレートしたいようです。

  • CPANにアクセスできる場合は、を使用できますFile::Tail

    これは純粋なPerl(XSではない)なので、CPANアクセスがない場合にソースにどのように実装されているかを確認できます。

  • また、PerlFAQ5(「perlでtail -fを実行するにはどうすればよいですか?」)も参照してください。

于 2013-03-27T13:11:57.643 に答える