stdoutに継続的に書き込みを行うプログラムを持っている人にとっては、「単一一致」オプションでgrepにパイプするだけです。grepは一致する文字列を見つけると終了し、grepにパイプされているプロセスの標準出力を閉じます。このイベントにより、プロセスが再び書き込みを行う限り、プログラムは自然に正常に終了します。
何が起こるかというと、grepが終了した後、プロセスが閉じたstdoutへの書き込みを試みると、プロセスはSIGPIPEを受け取ります。pingを使用した例を次に示します。そうしないと無期限に実行されます。
$ ping superuser.com | grep -m 1 "icmp_seq"
このコマンドは、最初に成功した「pong」と一致し、次にping
stdoutへの書き込みを試行して終了します。
しかしながら、
プロセスが再びstdoutに書き込むことは常に保証されているわけではないため、SIGPIPEが発生する可能性はありません(たとえば、ログファイルをテーリングするときに発生する可能性があります)。このシナリオで思いついた最高のソリューションには、ファイルへの書き込みが含まれます。改善できると思われる場合はコメントしてください:
$ { tail -f log_file & echo $! > pid; } | { grep -m1 "find_me" && kill -9 $(cat pid) && rm pid; }
これを分解する:
tail -f log_file & echo $! > pid
-ファイルを末尾にし、プロセスをバックグラウンドにアタッチし、PID($!
)をファイルに保存します。代わりにPIDを変数にエクスポートしようとしましたが、こことPIDが再び使用される間に競合状態があるようです。
{ ... ;}
- これらのコマンドをグループ化して、現在のコンテキストを維持しながら出力をgrepにパイプできるようにします(変数を保存および再利用する際に役立ちますが、その部分を動作させることができませんでした)
|
-左側の標準出力を右側の標準入力にパイプする
grep -m1 "find_me"
-ターゲット文字列を見つける
&& kill -9 $(cat pid)
- 一致する文字列が見つかったら、終了後にtail
プロセスを強制終了(SIGKILL) grep
&& rm pid
-作成したファイルを削除します
tail -f
ファイルと同様にプログラム出力も可能であると思っていたでしょう...間違っていますか?