出力をFIFOで分配する

出力をFIFOで分配する

私は次の方法を使用して非常に長いmake出力を配布しようとしています

mkfifo myfifo 
make 2>&1 | tee myfifo | grep -E "errors|warnings" myfifo > errors.log | cat myfifo

アイデアとしては、出力のサブセットをログ ファイルにコピーし、出力全体をコンソールの stdout にリダイレクトするというものです。

最初は動作しているように見えますが、突然停止し、Ctrl + Z を押すまでフリーズしたままになります。

プロセス置換の使用

make 2>&1 | tee >(grep -E "errors|warnings" > errors.log)

シェルはデフォルトで厳密な POSIX 準拠でコンパイルされているため、これは不可能です。

プラットフォーム - Ubuntu 風ディストリビューション。シェル bash 4.2 (利用可能なのは 1 つだけ)

答え1

それ

make 2>&1 | tee myfifo | grep -E "errors|warnings" myfifo > errors.log | cat myfifo
          P1           P2                                              P3

コマンドはあまり意味がありません。パイプを挟んで 4 つのコマンドを同時に開始します。

  • make 2>&1: stdoutとstderrはP1に送られます
  • tee myfifo: P1 から stdin、P2 に stdout。したがって、tee出力は両方myfifoと P2 に書き込まれます。
  • grep -E "errors|warnings" myfifo > errors.log: P2 からの stdin ですが、ファイル名 ( myfifo) を に渡しているためgrepgrepその stdin からは読み込まれません。 stdout は に送られerrors.log、P3 には何も書き込まれません。
  • cat myfifo: P3 からの stdin ですが、やはりcatファイル名が指定されているため、代わりにそれを読み取ります。つまり、 と の両方grepが同時にcat読み取りますmyfifo

P2 からは何も読み込まれないため、teeP2 がいっぱいになると はハングします。また、によって読み込まれたcatの部分も表示されません。myfifogrep

make 2>&1 | tee myfifo | grep -e errors -e warnings > errors.log | cat myfifo

が、あなたが意図しているものに近いと思います。ここでも P3 は使用されませんが、同時に|開始して待機するために を使用しています。cat

または、次のようにすることもできます。

make 2>&1 | tee myfifo & grep -e errors -e warnings > errors.log
wait

より多くの s が必要な場合はgrep、より多くの fifo が必要です。

make 2>&1 | tee fifo2grep1 fifo2grep2 &
grep errors fifo2grep1 > errors.log &
grep warnings fifo2grep2 > warnings.log
wait

をサポートするシステムでは/dev/fd/x、次の操作も実行できます。

make 2>&1 | { tee /dev/fd/3 | grep -e errors -e warnings 3>&-; } 3>&1

(これは通常、それをサポートするシェルでのプロセス置換によって行われることです)。

2 greps の場合は次のようになります。

make 2>&1 |
 {
   {
     tee /dev/fd/3 /dev/fd/4 |
       grep errors > errors.log 3>&- 4>&-
   } 4>&1 |
     grep warnings > warnings.log 3>&-
 } 3>&1

答え2

grep -E "errors|warnings" myfifo > errors.logパイプにデータがなくなると、cat myfifoパイプから読み取る次のコマンドはブロックされます。

質問を正しく理解していれば、すべてのメッセージを stdout に出力し、すべてのエラーおよび警告メッセージを にリダイレクトしたいということですねerrors.log。したがって、パイプを使用する場合は、次の 2 つを使用します。

 mkfifo pipe1 pipe2 
 make 2>&1 | tee pipe1 pipe2 | grep -E "errors|warnings" pipe1 > errors.log | cat pipe2

関連情報