stdoutとstderrをログファイルにコピーし、スクリプト自体のコンソールに残します。

stdoutとstderrをログファイルにコピーし、スクリプト自体のコンソールに残します。

Bashを使用してstderrとstdoutをログファイルにコピーしてコンソールに表示するにはどうすればよいですか?

execを使用してスクリプト自体でこれを実行したいと思います。

私は前に試しました

exec &>> log.out

echo "This is stdout"
echo "This is stderr" >&2

しかし、上記はコンソールに何も印刷しません。 Bashでどのようにこれを達成できますか?

答え1

あなたが探しているtee

man tee詳細より。

それを組み合わせるexecにはプロセスの交換。 (man bash詳細より。)

exec &> >(tee  log.out)
echo "This is stdout"
echo "This is stderr" >&2

答え2

この投稿が古い投稿であることを知っていますが、これを行うとどうなりますか?

echo "hi" >> log.txt #stdout -> log
echo "hi" | tee -a log.txt #stdout -> log & stdout
echo "hi" &>> log.txt #stdout & stderr -> log
echo "hi" |& tee -a log.txt #stdout & stderr -> log & stdout

もちろん、stdoutが必要な場合は定期的に印刷することもできます。

必要なストリームの組み合わせでこれを行うことができます。次の2つの基本コマンドを使用できます。

理解しやすく実装しやすい答えを持ってここに来なかったことを知っています。これが他の人に役立つことを願っています。

ところで、私のような愚かなノルムの場合、コマンドがtee実行するすべての作業はstdin入力をstdoutに出力し、ファイルを後続の引数として指定することです。-a追加を意味するので、コマンドを使用するたびにファイルを上書きしません。私が見つけた追加の質問があればこれBashをすばやく学ぶのに非常に便利なリソースです。

答え3

あなたはできます:

: > log # empty log file if necessary
{ { {

  ...the script

} 3>&- | tee -a log >&3 3>&-
exit "${PIPESTATUS[0]}"
} 2>&1 | tee -a log >&2 3>&-
} 3>&1
exit "${PIPESTATUS[0]}"

次のように書くこともできます。

: > log # empty log file if necessary
exec 2> >(tee -a log >&2) > >(tee -a log)

...the script

しかし、bashは)で始まるプロセスを待たないので、時々>(...コマンドが返された後に端末に何かを出力します。点灯しています。

いずれにしてもstdout、両方のソリューションでパイプを生成し、両方のコマンドが出力とエラーメッセージを独立して出力するため、出力バッファリングと出力とエラーメッセージが表示される順序に影響します。

答え4

別の方法は、関数内でリダイレクトを使用することです。

#!/bin/bash

function1 () {
    echo 'STDOUT from function 1'
    echo 'STDERR from function 1' >&2
}

function2 () {
    echo 'STDOUT from function 2'
    echo 'STDERR from function 2' >&2
}


function3 () {
    echo 'STDOUT from function 3'
    echo 'STDERR from function 3' >&2
}

main() {
    function1
    function2
    function3
}

main 2>&1 |tee log.txt

mainこれには他のすべての関数を呼び出す関数があります。これSTDOUTで機能にSTDERRリダイレクトします。maintee

関連情報