パイプの他の受信者に stderr を送信する

パイプの他の受信者に stderr を送信する

今私はこれを持っています:

 echo "$run_test" | bash 2>&1 | prepend "r2g-test:" "yellow";

これがすることは、stdout / stderrの各行の前に「r2g-test:」を追加することです。 stderrをstdoutに送るので、prependプログラムはすべてstdinなので、違いはわかりません。

prependstderrを別のインスタンスに送信する方法はありますかtee

たぶんこんなことはありませんか?

 echo "$run_test" | bash 2> $(prepend 'r2g-test:' 'red') | prepend 'r2g-test:' 'yellow';

プロセス置換を使用すると、次のように機能できます。

bash 2> >(prepend 'r2g-test:' 'red')

しかし、これまでstderrは端末に表示されません。

答え1

run_testまず、stdoutとstderrを生成するプログラムを作成しましょう。

$ run_test() { while sleep 0.2; do echo "Out $((++c))"; echo "err$c">&2; done; }

それでは、stdoutとstderrを別のフィルタに送信しましょう。インストールされていないので同じ目的prependで使用します。sed

$ exec 3>&2; { run_test | sed 's/^/stdout: /'; } 2>&1 1>&3 | sed 's/^/stderr: /'
stdout: Out 1
stderr: err1
stdout: Out 2
stderr: err2
stdout: Out 3
stderr: err3

どのように動作しますか?

  • exec 3>&2

    これにより、ファイル記述子3がstderrのコピーとして作成されます。

  • run_test | sed 's/^/stdout: /'

    これが実行され、標準出力の先頭にrun_test追加されます。stdout:

  • { run_test | sed 's/^/stdout: /'; } 2>&1 1>&3

    2>&stderrが次のパイプに移動するようにstderrをstdoutにリダイレクトします。 1>&3端末に表示されるように stdout を stderr にリダイレクトします。

  • { run_test | sed 's/^/stdout: /'; } 2>&1 1>&3 | sed 's/^/stderr: /'

    最後のパイプはrun_testのstderr(現在のstdout)をキャプチャして前に追加しますstderr:

プロセス交換の使用

$ run_test > >(sed 's/^/stdout: /') 2> >(stdbuf -oL sed 's/^/stderr: /' >&2)
stdout: Out 1
stderr: err1
stdout: Out 2
stderr: err2
stdout: Out 3
stderr: err3

上記はstdbufLinuxの標準を使用しています。他のオペレーティングシステムの場合は、同様のコマンドを探します。

関連情報