回答:
問題は、出力をリダイレクトすると、次のリダイレクトで使用できなくなることです。tee
サブシェルにパイプして、2番目のリダイレクトの出力を保持できます。
( cmd | tee -a file2 ) >> file1 2>&1
または、ターミナルで出力を見たい場合:
( cmd | tee -a file2 ) 2>&1 | tee -a file1
最初の標準エラー出力を追加することを避けるためにtee
することがfile1
、あなたには、いくつかのファイルディスクリプタ(例えば3)にあなたのコマンドの標準エラー出力をリダイレクトし、後でもう一度stdoutにこれを追加する必要があります:
( 2>&3 cmd | tee -a file2 ) >> file1 3>&1
# or
( 2>&3 cmd | tee -a file2 ) 3>&1 | tee -a file1
(ありがとう@ fra-san)
でzsh
:
cmd >& out+err.log > out.log
追加モードの場合:
cmd >>& out+err.log >> out.log
でzsh
、mult_ios
オプションが無効になっていない場合、ファイル記述子(ここでは1)が書き込みのために数回リダイレクトされると、シェルは組み込みを実装して、tee
すべてのターゲットに出力を複製します。
cmd >& file1 > file2
あなたが可能性:タグの標準出力(UNBUFFEREDをSED使用して、すなわち:sed -u ...
)、標準エラー出力にも(SEDそれはタグ付けを通過しなかったので、タグなし)stdoutに行くので、結果のログファイルに2を区別することができています。
以下は:で、低速(;やる...;それは真剣に代わりしばらく...のexemple Perlのスクリプトのために使用することによって、最適化することができ、すべての行でサブシェル&コマンドを産卵することを、exempleのために、やった!)、奇妙な「:など、しかし、それは(私が1つのリネーム標準出力にし、他の一つに、それにstderrを「通過falled」を追加する2 {}の段階を必要とするようだ)コンセプトの証明」、それが維持しようとします出力の順序は、可能な限りstdoutとstderrのほとんどです。
#basic principle (some un-necessary "{}" to visually help see the layers):
# { { complex command ;} | sed -e "s/^/TAGstdout/" ;} 2>&1 | read_stdin_and_redispatch
#exemple:
# complex command = a (slowed) ls of several things (some existing, others not)
# to see if the order of stdout&stderr is kept
#preparation, not needed for the "proof of concept", but needed for our specific exemple setup:
\rm out.file out_AND_err.file unknown unknown2
touch existing existing2 existing3
#and the (slow, too many execs, etc) "proof of concept":
uniquetag="_stdout_" # change this to something unique, that will NOT appear in all the commands outputs...
# avoid regexp characters ("+" "?" "*" etc) to make it easy to remove with another sed later on.
{
{ for f in existing unknown existing2 unknown2 existing3 ; do ls -l "$f" ; sleep 1; done ;
} | sed -u -e "s/^/${uniquetag}/" ;
} 2>&1 | while IFS="" read -r line ; do
case "$line" in
${uniquetag}*) printf "%s\n" "$line" | tee -a out_AND_err.file | sed -e "s/^${uniquetag}//" >> out.file ;;
*) printf "%s\n" "$line" >> out_AND_err.file ;;
esac;
done;
# see the results:
grep "^" out.file out_AND_err.file
ls unknown
)を使用してstderrに何かを印刷するのですか? >&2 echo "error"
大丈夫です。(2)tee
一度に複数のファイルに追加できます。(3)どうしてcat
代わりにgrep "^"
?(4)stderrの出力がで始まる場合、スクリプトは失敗し_stdout_
ます。(5)なぜですか?
ls loop
はstdoutとstderrの両方に出力され、混合(または代替)され、制御された順序で出力されます。そのため、stdoutのタグ付けにもかかわらず、stderr / stdoutの順序が維持されていることを確認できます2):gnu tailレギュラーテール(例:aix。)。3):grep "^"は両方のファイル名も表示します。4):これは変数によって変更できます。5。
uniquetag="banaNa11F453355B28E1158D4E516A2D3EDF96B3450406
...)
出力の順序が次のとおりでなければならない場合:stdout then stderr ; リダイレクトのみの解決策はありません。
stderrは一時ファイルに保存する必要があります
cmd 2>>file-err | tee -a file1 >>file2
cat file-err >> file1
rm file-err
説明:
1つの出力(stdoutやstderrなどのfd)を2つのファイルにリダイレクトする唯一の方法は、それを再現することです。このコマンドtee
は、ファイル記述子の内容を再現するための正しいツールです。そのため、2つのファイルに1つの出力を作成する最初のアイデアは、次のものを使用することです。
... | tee file1 file2
両方のファイル(1と2)にteeのstdinが再現され、teeの出力は未使用のままになります。ただし、追加(使用-a
)する必要があり、コピーは1つだけ必要です。これにより、両方の問題が解決されます。
... | tee -a file1 >>file2
電源にtee
標準出力(繰り返しに1)で我々は、コマンドのうち、標準エラー出力を直接摂取する必要があります。1つの方法として、順序が重要でない場合(出力の順序は(ほとんどの場合)生成されたままに保持され、最初に出力された方が最初に保存されます)。どちらか:
cmd 2>>file1 | tee -a file2 >>file1
cmd 2>>file1 > >( tee -a file2 >>file1 )
( cmd | tee -a file2 ) >> file1 2>&1
オプション2は一部のシェルでのみ機能します。オプション3は追加のサブシェル(低速)を使用しますが、ファイル名は1回のみ使用します。
ただし、stdoutを 最初にする必要がある場合(出力が生成される順序)、stderrを保存して、最後にファイルに追加する必要があります(最初のソリューションが投稿されます)。
sponge
。(cmd | tee -a out >> out+err) 2>&1 | sponge >> out+err
多様性のために:
システムがをサポートしている/dev/stderr
場合、
(cmd | tee -a /dev/stderr) 2>> file1 >> file2
働くでしょう。の標準出力cmd
は、パイプラインのstdoutとstderrの両方に送信されます。cmd
バイパスの標準エラーtee
は、パイプラインの標準エラーをバイパスして出てきます。
そう
cmd
、とcmd
混在しています。その場合、これらのストリームを正しいファイルに送信するだけです。
このようなアプローチ(Stéphaneの回答を含む)の
ほとんどと同様に、file1
行が乱れる可能性があります。
out+err
をout
意味しているのか分かりません。ファイル名?リダイレクトされるストリーム?