私はただやっているパイプラインを持っています
command1 | command2
したがって、command1のstdoutはcommand2に移動し、command1のstderrはターミナル(またはシェルのstdoutがどこにあるか)に移動します。
Command1のstderrを3番目のプロセス(command3
)stdoutがまだcommand2に行く間?
{ command1 2>&3 | command2; } 3>&1 1>&2 | command3
最大7つの他のファイル記述子を使用できます(3から9まで)。
さらに説明が必要な場合は、お問い合わせください。説明できます;-)
{ { echo a; echo >&2 b; } 2>&3 | sed >&2 's/$/1/'; } 3>&1 1>&2 | sed 's/$/2/'
出力:
b2
a1
2つのログファイルを生成します。
1。 stderr
のみ
2。 stderr
およびstdout
{ { { command 2>&1 1>&3; } | tee err-only.log; } 3>&1; } > err-and-stdout.log
command
がecho "stdout"; echo "stderr" >&2
その後、次のようにテストできます。
$ { { { echo out>&3;echo err>&1;}| tee err-only.log;} 3>&1;} > err-and-stdout.log
$ head err-only.log err-and-stdout.log
==> err-only.log <==
err
==> err-and-stdout.log <==
out
err
受け入れられた回答により、stdout
とstderr
が逆になります。それらを保持する方法は次のとおりです(その目的でグーグルするとこの投稿が表示されるため)。
{ command 2>&1 1>&3 3>&- | stderr_command; } 3>&1 1>&2 | stdout_command
通知:
command
に継承されないようにするには、3>&-
が必要です。 (これは、command
が内部で何をするかによって、予期しない結果をもたらす可能性があるためです。)最初に外側の部分:
3>&1
-fd for { ... }
はfd 1に設定されます(つまり、stdout
)1>&2
-fd 1 for { ... }
はfd 2に設定されます(つまり、stderr
)| stdout_command
-fd 1(以前はstdout
)はstdout_command
を介してパイプされます内部は外部からファイル記述子を継承します:
2>&1
-fd 2 for command
はfd 1に設定されます(つまり、外部パーツごとにstderr
)1>&3
-fd 1 for command
はfdが何であったかに設定されます(つまり、stdout
は外部パーツごとに)3>&-
-fd for command
は何も設定されていません(つまりclosed)| stderr_command
-fd 1(以前はstderr
)はstderr_command
を介してパイプされますfoo() {
echo a
echo b >&2
echo c
echo d >&2
}
{ foo 2>&1 1>&3 3>&- | sed -u 's/^/err: /'; } 3>&1 1>&2 | sed -u 's/^/out: /'
out: a
err: b
err: d
out: c
(a -> c
とb -> d
の間には同期の形式がないため、stderr_command
とstdout_command
の順序は常に不確定です。)
{ command1 | command2; } 2>&1 | command3
注意:commnd3
は、command2
stdout(存在する場合)も読み取ります。
これを回避するには、commnd2
stdoutを破棄します。
{ command1 | command2 >/dev/null; } 2>&1 | command3
ただし、command2
stdoutを保持するため(たとえば、ターミナル内)、
次に、他の私の回答をより複雑に参照してください。
{ { echo -e "a\nb\nc" >&2; echo "----"; } | sed 's/$/1/'; } 2>&1 | sed 's/$/2/'
出力:
a2
b2
c2
----12
プロセス置換の使用:
command1 > >(command2) 2> >(command3)
詳細は http://tldp.org/LDP/abs/html/process-sub.html を参照してください。
同じ効果はfifoでかなり簡単に達成できます。私はそれを行うための直接パイプ構文を知りません(それを見るのは気の利いたことです)。これは、FIFOでそれを行う方法です。
まず、stdout
とstderr
、outerr.sh
の両方に出力されるもの:
#!/bin/bash
echo "This goes to stdout"
echo "This goes to stderr" >&2
その後、次のようなことができます。
$ mkfifo err
$ wc -c err &
[1] 2546
$ ./outerr.sh 2>err | wc -c
20
20 err
[1]+ Done wc -c err
この方法では、最初にstderr
出力のリスナーを設定し、構文2>err
を使用して、次のコマンドで発生するライターが作成されるまでリスナーをブロックします。各wc -c
に20文字の入力があることがわかります。
使い続けたくない場合は、完了後にfifoをクリーンアップすることを忘れないでください(つまり、rm
)。他のコマンドがファイル引数ではなくstdin
への入力を必要とする場合、wc -c < err
のような入力リダイレクトを使用することもできます。
通常どおりstdoutをパイプしますが、stderrリダイレクトにはBashプロセスの置換を使用します。
some_command 2> >(command of stderr) | command of stdout
ヘッダー:#!/bin/bash