どうやって達成できますか?
cmd >> file1 2>&1 1>>file2
つまり、標準出力そしてstderrは1つのファイル(ファイル1)にリダイレクトする必要があり、stdout(ファイル2)のみを別のファイルにリダイレクトする必要があります(どちらも追加モードで)。
答え1
問題は、出力をリダイレクトするときに次のリダイレクトに使用できなくなることです。tee
2番目のリダイレクトの出力を維持するために、サブシェルでパイプを使用できます。
( cmd | tee -a file2 ) >> file1 2>&1
または、端末から出力を表示するには、次の手順を実行します。
( cmd | tee -a file2 ) 2>&1 | tee -a file1
tee
に最初のstderrを追加したくない場合は、file1
コマンドのstderrをいくつかのファイル記述子(例: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に感謝します)
答え2
そしてzsh
:
cmd >& out+err.log > out.log
追加モードでは:
cmd >>& out+err.log >> out.log
でzsh
このオプションが無効になっていない場合、ファイル記述子(ここでは1)が書き込み用に複数回リダイレクトされると、シェルは出力をすべてのターゲットにコピーする組み込み関数をmult_ios
実装します。tee
答え3
次のことができます。 stdoutを表示し(つまりsed -u ...
:)、stderrもstdoutに移動し(sedマークを通過しないため表示されません)、生成されたログファイルから2を区別できます。
次のように:はい遅い(たとえば、while ...; do ...; doneの代わりにperlスクリプトを使用すると、真剣に最適化される可能性があります。たとえば、すべての行にサブシェルとコマンドが生成されます!)奇妙な(あるステップでstdoutの名前を変更し、別のステップで「失敗」stderrを追加するには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
答え4
多様性のため:
あなたのシステムがそれをサポートしているなら/dev/stderr
、
(cmd | tee -a /dev/stderr) 2>> file1 >> file2
動作します。標準出力はcmd
stdout および stderr パイプに送信されます。標準エラーはパイプされたstderrをcmd
バイパスしますtee
。
だから
- パイプの標準出力はパイプ
cmd
の標準出力にすぎません。 - パイプの stderr は
cmd
stdout と stderr の混合です。
その後、これらのストリームを正しいファイルに送信するのは簡単です。
ほぼすべての同様の方法(含む)と同様にスティーブンの答え)、
file1
これは線が正しく機能しない可能性があります。