テスト文字列に一致するログファイルの最後の行を取得し、別のログファイルに出力したいと思います。
さまざまなテキスト文字列をテストし、出力に応じてさまざまなログファイルに送信する必要があります。
私はこれを使用しています:
tail -f -n 1 input.log | grep string1 >>output1.log
その後、次のようにテストを繰り返したいと思います。
tail -f -n 1 input.log | grep string2 >>output2.log
tail -f -n 1 input.log | grep string3 >>output3.log
効率的な単一のbashスクリプトでこれをどのように達成できますか?
ベストアンサー1
grepの代わりにawkを使用してください。
awk '/string1/ { print >> "output1.log" ; fflush() }
/string2/ { print >> "output2.log" ; fflush() }
/string3/ { print >> "output3.log" ; fflush() }' input.log
この出力みんな行を対応するoutput.logファイルと一致させます。それはあなたの矛盾tail -f
と要件を理解できないからですtail -n 1
。input.log
現在の最後の行から始めるには、tail -f -n 1
スクリプトをパイプしawk
てinput.log
その行の終わりを削除します。例えば
tail -f -n 1 input.log | awk '...same awk script as above...'
tee
また、grep
それを行うことができますし、プロセスの交換
(しかし、かなり遅くなるでしょう):
tee >(grep --line-buffered string1 >> output1.log) \
>(grep --line-buffered string2 >> output2.log) \
>(grep --line-buffered string3 >> output3.log) < input.log
または
tail -f -n 1 input.log | tee .....
メモ:fflush()
in -solutionawk
およびin-solution--line-buffered
オプションは、(または他の無限プロセス)の出力をまたはにパイプする場合にのみ必要です。tee
tail -f
awk
tee
これがなければ、出力ファイルは出力バッファ(awkまたはgrep)がいっぱいになったときにのみ書き込まれます。ジョブがバッファに書き込まれていない出力で中断された場合(たとえば、Ctrl-Cを押す)、すべての出力は依然として失われます。バッファ。
これを使用すると、両方のソリューションがはるかに遅くなります(書き込みごとに出力をフラッシュするため)。ただし、入力ファイルが非常に大きくない場合は問題になりません。
ちなみに、これは入力の終わりに問題ではありません。この場合、awk と grep はどちらも終了する前に出力バッファを自動的にフラッシュします。
別の選択肢は、サブシェルでパイプawk
(または)を実行してCtrl-Cの割り込み信号をキャプチャして無視することです。tee
例えば
tail -f input.log | (
trap '' INT
awk '/string1/ { print >> "output1.log" }
/string2/ { print >> "output2.log" }
/string3/ { print >> "output3.log" }'
)
tail -f
Ctrl-Cを押すと影響しますが(終了)、実行中のサブシェルはawk
それを無視します。 awk
出力バッファをフラッシュし、tail
入力が完了して終了すると終了します。
バラよりawkスクリプトからCtrl-Cをキャプチャする別の例/説明。
ログファイルに従わない場合は、tail
's-f
オプションを使用しないでください。
tail -n 1 | .....
3つの文字列のすべての最後の項目をその出力ファイルに印刷するGuyの回答を使用するか調べます。