1

コマンドの 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
4

2 に答える 2

1

stderr を ./tmperr にリダイレクトし、stdout を ./tmpout にリダイレクトして、バックグラウンドで 2 つのスクリプトを実行し、それぞれが tmperr または tmpout から連続して 1 行を読み取り、その行を削除するのはどうですか? これは明らかに理想的ではありませんが、実際の foo.sh スクリプトにかなりの遅延がある場合は、これでうまくいくはずです。

于 2015-06-16T15:33:50.157 に答える