web-dev-qa-db-ja.com

なぜ `tail-fではないのですか…| grep -q… `一致するものが見つかったら終了しますか?

私はかなり標準的なtail + grepをやっています:

tail -f some_log_file.txt | grep -q known-string

-qなしでコマンドを実行した場合:

tail -f some_log_file.txt | grep known-string

出力が表示されます:

[Tue Feb 12 11:32:45 2019] known-string.

だから私はgrepが一致していることを知っています。ただし、-qを追加すると、grepコマンドが終了せず、出力を待つだけでハングします...マニュアルページに「一致するものが見つかった場合はステータスなしですぐに終了します」と表示されます。

   -q, --quiet, --silent
          Quiet;  do  not  write  anything  to  standard   output.    Exit
          immediately  with  zero status if any match is found, even if an
          error was detected.  Also see the -s or --no-messages option.

-qが私のgrepを終了させない理由を誰かが説明できますか? && beepを最後までチェーンしようとしているので、一致するものが見つかるとgrepがビープ音を鳴らしますが、終了させることができない限り、機能しません。

1
machineghost

StackOverflowの投稿から 'grep -q'は 'tail -f'で終了しません

tail -fはファイルを読み取り、後で追加された行を表示しますが、終了しません(SIGTERMのようなシグナルが送信されない限り)。 grepは、ここではブロック部分ではありません、tail -fです。 grepはパイプが閉じられるまでパイプから読み取りますが、それはtail -fは終了せず、パイプを開いたままにします。


あなたの問題の解決策はおそらく(テストされておらず、パフォーマンスが悪い可能性が非常に高い)でしょう:

tail -f logfile | while read line; do
  echo $line | grep -q 'find me to quit' && break;
done

あなたはリンクされた投稿でより多くの情報と解決策を見つけるでしょう。

3
harrymc

grepは実行を続けますが、tailは終了し、パイプは消えます。 このバグレポートログ あなたと非常によく似たユースケースから始まります:

tailgrepを使用して、特定のパターンが表示されるまでファイルを追跡したいと思います。ただし、tailが終了しても、grepは終了しません。

_$ echo xxx > /tmp/blabla
$ tail -f /tmp/blabla |grep -m1 --line-buffered "xxx"
xxx
_

現在、tailは、_/tmp/blabla_に再度書き込んだ場合にのみ、読み取りを試みて終了します。

これはどうあるべきか?

そこでの説明:

tailはSIGPIPEで終了しますが、シグナルはwrite()でのみ取得されるため、tailが終了する前にファイル内のデータをさらに取得する必要があります。

私の知る限り、この正確なメカニズムは非常に一般的です。多くのツールはafterを終了し、壊れたパイプに何かを書き込もうとしますが、これはバグではありません。

それからこの願いが来ました:

tailは永遠にぶらぶらする可能性があるため、パイプのもう一方の端が消えるのに対応するために特別な手順を実行する必要があります。

そして最後に:

実装先:
https://git.sv.gnu.org/cgit/coreutils.git/commit/?id=v8.27-42-gce0415f

実際、tail from GNU coreutils 8.28で問題を再現しようとすると、できません。ツールはすぐに終了します。

2