bash stdout + stderrを1つのファイルにリダイレクトし、stderrを別のファイルにリダイレクトします。

bash stdout + stderrを1つのファイルにリダイレクトし、stderrを別のファイルにリダイレクトします。

すべての出力をファイルにリダイレクトし、stderrも別のファイルにリダイレクトする必要があります。これは簡単なことですか?

この例では、私のコマンドが次のようになるとします。

php /tmp/doWork.php

以下を使用して、出力を別々のファイルに出力できます。

php /tmp/doWork.php 1> /tmp/stdout_file 2> /tmp/stderr_file

に基づいてこれ、私は次のことを試みます:

php /tmp/doWork.php &> /tmp/stdboth_file 2> /tmp/stderr_file

しかし、これは単にstdoutとstderrを置く/tmp/stdboth_fileだけです/tmp/stderr_file

答え1

zsh以下zshの特徴がありますmultios

your-cmd 2> stdout+stderr.log >&2 2> stderr.log

fd 2は2回リダイレクトされるため、実装はzshそれteeを2つのファイルに内部的に送信します。

bash(またはBourneなどのシェル(ここで動作するためにzsh無効にする必要がある場合を除くmultios))を使用して、tee次のように手動で実行できます。

{ your-cmd 2>&1 >&3 3>&- | tee stderr.log 3>&-; } > stderr+stdout.log 3>&1

your-cmdzsh( . の終了状態が失われ$pipestatus[1]ても、その内容がbash含まれています"${PIPESTATUS[0]}"(リダイレクトがstderr+stdout.log失敗しなかったと仮定)。

pidを記録するにはyour-cmd

{ sh -ec 'echo "$$" > /var/run/pidfile; exec your-cmd' 2>&1 >&3 3>&- |
   tee stderr.log 3>&-; } > stderr+stdout.log 3>&1

そしてyashそれプロセスリダイレクト特徴:

your-cmd > stdout+stderr.log 2>(tee stderr.log)

(ただし、yashコマンドが終了するのを待たないため、tee次のコマンドを実行するまでログファイルが完了しないことがあります。)

同様のことができます(同じ注意事項があります)。プロセスの交換一緒にしてください:bashzshksh93

{ your-cmd 2> >(tee stderr.log); } > stderr+stdout.log

バックグラウンドで実行してPIDを取得するには:

(exec your-cmd 2> >(tee stderr.log)) > stderr+stdout.log & pid=$!

そしてrc

{your-cmd |[2=0] tee stderr.log} > stdout+stderr.log

rcパイプを使用すると、パイプに関連付けられたファイル記述子を指定できます。他のシェルでは、左側のコマンドのfd 1と右側のコマンドのfd 0は常に同じです(したがって、ファイル記述子を移動するためにfd 3を使用して上記の小さなダンスを行います)。または、失敗するrcと失敗が報告されますが、正確な数字が失われる可能性があります。your-cmdtee

関連情報