特定の文字列が観察されるまでコマンドの出力を「監視」してから終了する


29

特定の文字列が観察されて終了するまで、コマンドの出力をプログラムで監視する方法を探しています。これはこの質問に非常に似ていますが、ファイルをテーリングする代わりに、コマンドを「テール」にします。

何かのようなもの:

watch -n1 my_cmd | grep -m 1 "文字列Imを探しています"

(しかし、これは私には機能しません。)

更新:「my_cmd」はテキストを継続的に出力するのではなく、文字列が見つかるまで繰り返し呼び出す必要があることを明確にする必要があります(これが「watch」コマンドを考えた理由です)。この点で、「my_cmd」は、ps、ls、lsof、lastなど、他の多くのUNIXコマンドと同様です。


tail -fファイルと同様にプログラム出力も可能であると思っていたでしょう...間違っていますか?
ジョアニス

@ジョアニス。あなたは正しいですが、私の場合、「my_cmd」は継続的に出力を生成せず、繰り返し呼び出す必要があります(ほとんどのコマンド:ps、ls、lsofなど)
gdw2

回答:


41

ループを使用します。

until my_cmd | grep -m 1 "String Im Looking For"; do : ; done

の代わりに:sleep 1CPUを緩和するために(または0.2)を使用できます。

grepがコマンドの出力で文字列を見つけるまで、ループが実行されます。-m 1は、「1回の一致で十分」を意味します。つまり、grepは最初の一致を検出した後、検索を停止します。

またgrep -q、最初の一致を見つけた後、一致する行を出力せずに終了するwhichを使用することもできます。


このコマンドの説明をいただければ幸いです。
マークW

@MarkW:更新。
choroba

grep -q別のオプションである他の誰かが言及しました。文字列を見つけた後、grepは終了します。

このコマンドは問題のコマンドを繰り返し実行することに注意してください。これは望ましい場合と望ましくない場合があります。
エイドリアン

1
@A__:OPの「更新」に記載されているとおりです。
チョロバ

11
watch -e "! my_cmd | grep -m 1 \"String Im Looking For\""
  • ! コマンドパイプラインの終了コードを無効にします
  • grep -m 1 文字列が見つかると終了します
  • watch -e エラーが発生した場合に戻ります

ただし、これは、一致する行を実際に表示するように改善できます。


詳細な説明に感謝しますが、私にはうまくいきません。私のwatchコマンド(CentOS)には-eフラグがありません(実際には問題ではありません)。ただし、さらに重要なのは、文字列が見つかった場合、ウォッチは実行を継続し、終了しないことです。ときようですgrep -m終了は、それだけでキルを終了しmy_cmdますが、ありませんwatch
gdw2

いいえ、問題ではありません! "-e"フラグは、コマンドに0以外のエラーコードがある場合に監視を終了することを意味します。とにかく、知っておくと良いのは、私のUbuntu 11.10のインストールではすべて問題ありません。また、非常に古いコマンドラインツールに関してMac OSXで問題が発生することもあります。これまでのところ、最新のソフトウェアを入手するためにMacポートを使用しています。
数学

パターンが見つかった場合、これは停止しますが、それが発生するまで出力は表示されません
Mark

あなたはそのために雇用するかもしれteeませんが、これは誤解を招く改行を導入します、私は今すぐ回避する方法がわかりません:watch -n1 -e "! date | tee /dev/tty | grep --color -m 1 \"17\""
数学

ええ、これは私にはうまくいきませんでした。watch文字列が見つかると監視を忠実に停止しますが、実際にはキーを押すまで終了しません。とても近い。
mlissner

8

stdoutに継続的に書き込みを行うプログラムを持っている人にとっては、「単一一致」オプションでgrepにパイプするだけです。grepは一致する文字列を見つけると終了し、grepにパイプされているプロセスの標準出力を閉じます。このイベントにより、プロセスが再び書き込みを行う限り、プログラム自然に正常に終了ます。

何が起こるかというと、grepが終了した後、プロセスが閉じたstdoutへの書き込みを試みると、プロセスはSIGPIPEを受け取ります。pingを使用した例を次に示します。そうしないと無期限に実行されます。

$ ping superuser.com | grep -m 1 "icmp_seq"

このコマンドは、最初に成功した「pong」と一致し、次にpingstdoutへの書き込みを試行して終了します。


しかしながら、

プロセスが再びstdoutに書き込むことは常に保証されているわけではないため、SIGPIPEが発生する可能性はありません(たとえば、ログファイルをテーリングするときに発生する可能性があります)。このシナリオで思いついた最高のソリューションには、ファイルへの書き込みが含まれます。改善できると思われる場合はコメントしてください:

$ { tail -f log_file & echo $! > pid; } | { grep -m1 "find_me" && kill -9 $(cat pid) && rm pid; }

これを分解する:

  1. tail -f log_file & echo $! > pid-ファイルを末尾にし、プロセスをバックグラウンドにアタッチし、PID($!)をファイルに保存します。代わりにPIDを変数にエクスポートしようとしましたが、こことPIDが再び使用される間に競合状態があるようです。
  2. { ... ;}- これらのコマンドをグループ化して、現在のコンテキストを維持しながら出力をgrepにパイプできるようにします(変数を保存および再利用する際に役立ちますが、その部分を動作させることができませんでした)
  3. | -左側の標準出力を右側の標準入力にパイプする
  4. grep -m1 "find_me" -ターゲット文字列を見つける
  5. && kill -9 $(cat pid)- 一致する文字列が見つかったら終了tailプロセスを強制終了(SIGKILL) grep
  6. && rm pid -作成したファイルを削除します

0
my_cmd | tail +1f | sed '/String Im Looking For/q'

構文がtailサポートされていない場合は+1f、を試してくださいtail -f -n +1。(-n +1最初から開始するように指示tail -fします。デフォルトでは、出力の最後の10行から開始します。)


質問の更新をご覧ください。
gdw2

0

プログラム呼び出しの結果をファイルに追加します。次にtail -f、そのファイル。そのように動作するはずです...私は願っています。

そのプログラムの呼び出しを再開するときは、探しているものがすぐに再び一致しないように、ファイルを消去するか、意味不明なファイルを追加する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.