
さて、このようなスクリプトがあるとしましょう。
log_files=(output_{console,stdout,stderr}.log)
do_stuff 2>"${log_files[2]}" 1>"${log_files[1]}"
"${log_files[1]}"
この関数はstdoutをstderrにリダイレクトする必要がありますが、stdoutとstderrの"${log_files[2]}"
両方をリダイレクトしたいと思います。"${log_files[0]}"
これはどのように達成できますか?
答え1
これはzshではるかに簡単です。multios
同じfdに複数のリダイレクトがある場合、シェルは内部魔法を実行して出力をすべてのターゲットに送信します。たとえば、次のようになります。
% do_stuff > stdout.log 2> stderr.log &> both.log
(冗長出力を処理する中間プロセスによって、stdoutとstderrへの出力順序が混乱する可能性があります。)
答え2
ティー
考えてecho "foo" | tee --append log.txt
聞いてくださいティー
ファイルおよびファイル記述子 1 に「foo」を送信します。
これにより、「foo」が一対のファイルに保存されます。
echo "foo" | tee --append one.txt >> two.txt
したがって、各着信テキストを一対のファイルに書き込む一対のサブシェルにリダイレクトできます。
名前付きパイプ
さらに柔軟性が必要な場合は、名前付きパイプを作成し、結果に任意のロジックを適用することもできます。
$ mkfifo /tmp/stdout
$ mkfifo /tmp/stderr
すでに行っているように、ファイル記述子1と2を送信します。別のターミナルタブまたは背景デーモンで実行するか、tail -f
それに対応するコマンドを実行して、各ターミナルでテキスト行を検索します。先入選出リアルタイム。正規表現でフィルタリングし、タイムスタンプで飾り、必要な操作を行い、好きなだけシンクに結果を記録します。
答え3
または、名前付きパイプなしでこれを行うには、次の質問に対する回答を使用できます。https://stackoverflow.com/questions/16497317/piping-both-stdout-and-stderr-in-bash
stdoutとstderrをそれぞれ独自のteeコピーにパイプし、両方を同じファイルに追加し、必要な各ファイルに書き込みます。
しかし、teeのすべての実装がこれを安全に実行するわけではないので、場合によっては、「両方」ファイル全体にstdoutブロックとstderrブロックが奇妙に散在している可能性があります。
私が知っている限り、teeには安全な行ベースのバッファリングを強制する方法はありません。