コマンドの stdout と stderr の両方をログ ファイルに記録するのは非常に簡単です。
./foo.sh &> log.txt
問題は、ログ ファイルを調べたときに、どの行がどのストリームから来たのかわからなくなることです。これは、stdout と stderr を 2 つの別個のファイルにリダイレクトすることで修正できますが、出力の時系列とインターリーブが失われます。
別の解決策は、3 つのファイルにリダイレクトすることです。1 つは stdout、1 つは stderr、および 1 つは両方を組み合わせたものです。何かのようなもの:
./foo.sh 2> >(tee stderr | tee -a combined) 1> >(tee stdout | tee -a combined)
しかし、非常に多くのファイルを持つことはあまりエレガントではありません (そして、このコマンドは依然として出力のコピーをシェルにダンプします)。
stderr メッセージのみを赤で表示する興味深い bash 関数を見つけました。
color()(set -o pipefail;"$@" 2>&1>&3|sed $'s,.*,\e[31m&\e[m,'>&2)3>&1
ただし、出力の順序は保持されず、結果はテキスト エディターで読み取ることができません。に対して次のプログラムがあるとしますfoo.sh
。
for i in 1 2; do
for j in 1 2; do
printf '%s\n' "out $i"
done
for k in 1 2; do
printf '%s\n' "err $i" >&2
done
done
実行するとcolor ./foo.sh
次が生成されます。
out 1
out 1
out 2
out 2
[31merr 1[m
[31merr 1[m
[31merr 2[m
[31merr 2[m
単一のログ ファイルでこのような結果になるのはどうしてでしょうか?
@| out 1
@| out 1
$| err 1
$| err 1
@| out 2
@| out 2
$| err 2
$| err 2