grep
連続ストリームで使用することは可能ですか?
私が言っているのは一種のtail -f <file>
コマンドですが、grep
私が興味を持っている行だけを保持するために出力を使用しています。
私は試しましたtail -f <file> | grep pattern
が、それが完了するのはgrep
一度しか実行できないようtail
です、つまり絶対に実行できないようです。
tail -f file
動作します(新しい出力はリアルタイムで表示されます)
grep
連続ストリームで使用することは可能ですか?
私が言っているのは一種のtail -f <file>
コマンドですが、grep
私が興味を持っている行だけを保持するために出力を使用しています。
私は試しましたtail -f <file> | grep pattern
が、それが完了するのはgrep
一度しか実行できないようtail
です、つまり絶対に実行できないようです。
tail -f file
動作します(新しい出力はリアルタイムで表示されます)
回答:
grep
BSD grep(FreeBSD、Mac OS Xなど)を使用する場合、のラインバッファリングモードをオンにします。
tail -f file | grep --line-buffered my_pattern
デフォルトでフラッシュするため(GNU grep(ほとんどのLinuxで使用))にこれを行う必要はありません(SmartOS、AIX、QNXなどの他のUnixライクではYMMV)。
strace
。なし--line-buffered
では機能しません。
tail -f | grep
、--line-buffered
私のためにそれを解決してくれました(Ubuntu 14.04では、GNU grepバージョン2.16)。「stdoutがttyである場合、ラインバッファリングを使用する」ロジックはどこに実装されていますか?でgit.savannah.gnu.org/cgit/grep.git/tree/src/grep.c、line_buffered
唯一の引数パーサによって設定されています。
--line-buffered
、何も出力しません。しかし、テスト後、GNU grepはあなたが記述したことを実行しているように見えます。したがって、ほとんどのUnixと同様に、プラットフォームの実装に依存します。質問はプラットフォームを指定していないので、あなたの情報が虚偽であるように思われる- BSD grepのためのコードを見直し、GNU grepのそれを比較した後、行動は間違いなく--line-バッファリングオプションによって制御されています。デフォルトでは、GNU grepのみがフラッシュします。
ずっと使ってtail -f <file> | grep <pattern>
います。
終了するまでではなく、grepがフラッシュするまで待機します(私はUbuntuを使用しています)。
あなたの問題は、grepが出力バッファリングを使用していることだと思います。試す
tail -f file | stdbuf -o0 grep my_pattern
grepの出力バッファリングモードをunbufferedに設定します。
grep
。
unbuffer
(expect-dev
debian のパッケージ内で)kingです。そのため、stdbufではなくunbufferを使用します。
top
stdbufおよびunbuffer との対話と比較してください)。そして、実際には「魔法の」解決策はありません。たとえば、バッファリングが失敗することもあります。たとえば、awkは異なるバッファ実装を使用します(stdbufも失敗します)。
ほとんどの場合、それは可能でtail -f /var/log/some.log |grep foo
、問題なく機能します。
実行中のログファイルで複数のgrepsを使用する必要があり、出力が得られない場合は、次の--line-buffered
ようにスイッチを中央の grep に固定する必要がある場合があります。
tail -f /var/log/some.log | grep --line-buffered foo | grep bar
あなたはこの答えを拡張と考えるかもしれません..通常私は使用しています
tail -F <fileName> | grep --line-buffered <pattern> -A 3 -B 5
-Fは、ファイルを回転する場合に適しています(ファイルを回転すると、-fは正しく機能しません)
-Aおよび-Bは、パターンオカレンスの直前と直後の行を取得するのに役立ちます。これらのブロックは、破線のセパレータの間に表示されます。
しかし、私にとっては、次のことを好む
tail -F <file> | less
これは、ストリーミングされたログ内を検索する場合に非常に役立ちます。前後に行って深く見ます
grep -C 3 <pattern>
、Nが同じ場合、-A <N>と-B <N>を置き換えます。
誰もが私の通常の目的にこれを提供するのを見ていませんでした:
less +F <file>
ctrl + c
/<search term>
<enter>
shift + f
私はこれを好みます。なぜならctrl + c
、いつでもファイルを停止してナビゲートし、次にヒットshift + f
するだけでライブのストリーミング検索に戻ることができるからです。
sedの方が適しています(ストリームエディター)
tail -n0 -f <file> | sed -n '/search string/p'
そして、特定の文字列が見つかったら、tailコマンドを終了したい場合は、次のようにします。
tail --pid=$(($BASHPID+1)) -n0 -f <file> | sed -n '/search string/{p; q}'
明らかにバシズム:$ BASHPIDはtailコマンドのプロセスIDです。sedコマンドはパイプの末尾の次にあるため、sedプロセスIDは$ BASHPID + 1になります。
$BASHPID+1
)で開始された次のプロセスがあなたのものであるという仮定は多くの状況で誤りであり、これはおそらくOPが尋ねようとしていたバッファリングの問題を解決するためには何もしません。特に、ここで推奨sed
するgrep
ことは、単に(疑わしい)好みの問題のようです。(それがあなたが配達しようとしているポイントp;q
であるgrep -m 1
なら、あなたは行動を得ることができます。)
--line-buffered
はそうではありませんでした。私は心からマイナス1を理解していません
はい、これは実際には問題なく動作します。Grep
ほとんどのUnixコマンドは、一度に1行ずつストリームを操作します。末尾から出てくる各行は分析され、一致する場合は渡されます。
grep
、パイプ・チェーンの最後のコマンドであるあなたが説明として、それが動作します。ただし、中央にある場合は、一度に約8kの出力をバッファリングします。
次の1つのコマンドでうまくいきます(Suse)。
mail-srv:/var/log # tail -f /var/log/mail.info |grep --line-buffered LOGIN >> logins_to_mail
メールサービスへのログインの収集
あなたは確かに成功しません
tail -f /var/log/foo.log |grep --line-buffered string2search
テールのエイリアスとして「colortail」を使用する場合。バッシュで
alias tail='colortail -n 30'
タイプエイリアスでこれが出力されるかどうかを確認できます colortail -n 30
ます それからあなたはあなたの犯人を持っています:)
解決:
でエイリアスを削除する
unalias tail
このコマンドで「実際の」テールバイナリを使用していることを確認してください
type tail
これは次のようなものを出力するはずです:
tail is /usr/bin/tail
そして、あなたはあなたのコマンドを実行することができます
tail -f foo.log |grep --line-buffered something
幸運を。
行バッファーオプションがない場合は、grepの代わりにawk(別の優れたbashユーティリティ)を使用してください。テールからデータを継続的にストリーミングします。
これがgrepの使い方です
tail -f <file> | grep pattern
これがawkの使い方です
tail -f <file> | awk '/pattern/{print $0}'
{print $0}
印刷は条件が満たされたときのデフォルトのアクションであるため、は冗長です。)