web-dev-qa-db-ja.com

`tail -f`のリアルタイム出力にフィルターを適用するには?

tail -f path

上記はファイルへの変更を即座に出力しますが、出力にフィルターを適用し、キーワードxxxが含まれている場合にのみ表示します。

これにどのように取り組みますか?

61
wamp

Unixでは、あるプログラムの出力を別のプログラムにパイプすることができます。

したがって、尾をフィルタリングするには、grepを使用できます。

tail -f path | grep your-search-filter
87
AddersUK

短い答え:_tail -f somefile | grep somepattern_

ただし、これでは不十分な傾向があります。頻繁にローテーションされるファイルをテーリングしているとしましょう(デバッグログの場合、複数回ローテーションされる可能性があります)。その場合、_tail -F_はあなたの友達です。違いを調べさせていただきます。

しかし、_tail -f_と_tail -F_は最初に一連の行を出力します。これは、多くの場合、このユースケースでは望ましくないため、この場合は_-n0_を追加します

_tail -F -n0 somefile | grep somepattern
_

他のフィルタリングを実行するまでは問題ありませんが、バッファリングに注意する必要があります。 stdoutは、デフォルトでラインバッファリングされます端末への書き込み時ですが、パイプへの書き込み時に完全にバッファリングされます。したがって、tailは明示的にラインバッファリングされている(または各行の終わりで出力がフラッシュされる)ため、次のコードはそれらが見つかるとすぐにラインを発行し、grepも出力が端末に送られるためラインバッファリングされます。

_tail -F -n0 somefile | grep somepattern
_

しかし、次に、awkcutなどを使用して、出力をさらに処理することにします。

_tail -F -n0 somefile | grep somepattern | awk '{print $3}'
_

そして今、あなたはあなたの出力がどこに行ったのか不思議に思います...ログの量によっては、あなたは出力を得ることがわかるかもしれませんが、grepの標準出力が完全にバッファリングされた方法で動作しているので、それは一度にページになります、したがってawkは一度に4kBの入力を受け取ります(デフォルト)。

この場合、_--line-buffered_オプションを使用することで、grepにstdout行を常にバッファリングするように指示できます。

_tail -F -n0 somefile | grep --line-buffered somepattern | ...
_

ただし、ほとんどのコマンドには_--line-buffered_のようなものはありません。よりスクリプト可能なツールの場合は、関数を使用して出力をフラッシュできます(たとえば、awkでは、関数はfflush()で、Cと同じ名前を共有します。PerlやPythonも同様です)。

cutのようなものを使用すると、運が悪くなる可能性があります。 ...しかし、unbufferを検索してみてください。これは、expectツールチェーンによって提供されたものだと思います(私はこれを使用したことがありません)。

これがお役に立てば幸いです。

乾杯、キャメロン

16
Cameron Kerr

複数のパイプとgrepsを使用して、grep -vで除外したり、grep -iで大文字と小文字を区別しないようにしたりできます。

例:tail -100f/var/log/messages | grep -V ACPI | grep -i ata

末尾から100行のテーリングを開始し、テーリングを維持します。最初にACPIの行を除外し、次にata、ATA、またはそれらの組み合わせの行を表示します。

もう1つの便利なものは、ABCオプションで、After、Before、Contextの各行(前後の行)です。

2
Ronald Pottol