web-dev-qa-db-ja.com

シェルスクリプトの通常のようにstdoutをファイルに、stderrをファイルに、stdout + stderrをファイルに保存し、stdout + stderrを端末に取得する方法

シェルスクリプトの通常のように、stdoutを1つのファイルに、stderrを別のファイルに、stdout + stderrを3番目のファイルに保存し、stdout + stderrをターミナルに保存するにはどうすればよいですか?

私はこれを他の場所で見つけました:

exec > >(tee std_out) 2> >(tee err_out >&2)
ls # Should got to std_out
fsdfs # Command not found goes to err_out

本当に近いです。 bash test.sh 2>&1 | tee outputその後は機能しますが、スクリプトの実行方法にアクセスできません。これは、cicdシステムです。 execを使用してスクリプト内から「結合出力」を実行できるようにする必要があります。

CI/CDライブラリを作成していますが、クライアントがライブラリを使用する目的がわからないので、それぞれの使用例を説明します。

2
Levi

単にアプローチを拡張する:

_exec 2> >(tee -a stderr stdall) 1> >(tee -a stdout stdall)
_

標準エラーはstderrという名前のファイルに書き込まれ、標準出力はstdoutに書き込まれます。また、標準エラーと標準出力の両方がコンソールに書き込まれます(または2つのファイル記述子が時間execが実行されます)とstdallまで。
_tee -a_(追加)は、stdallが書き込みを開始する2番目のteeによって上書きされないようにするために必要です。

リダイレクトが実行される 順序 が関係することに注意してください。2番目のプロセス置換は最初のリダイレクトの影響を受けます。つまり、それが発生したエラーは>(tee -a stderr stdall)に送信されます。もちろん、この副作用を回避するために、2番目のプロセス置換の標準エラーを_/dev/null_にリダイレクトできます。標準エラーの前に標準出力をリダイレクトすると、すべてのエラーがstdoutおよびstdallにも送信されます。

Bashのプロセス置換のコマンドは 非同期 で実行されるため、出力が生成順に表示されることを保証する方法はありません。さらに悪いことに、標準出力と標準エラーのフラグメントは、同じ行に表示される可能性があります。

3
fra-san

スクリプトは、bashの> >(...)構成に依存する代わりに、_$0_(無限再帰を回避するために環境変数を設定および確認する)を介して自分自身を実行できます。IMLEは気まぐれで信頼性が高くありません。

_if [ "$REDIRECTED" != 1 ]; then
        export REDIRECTED=1
        set -o pipefail
        { { "$0" | tee stdout >&3; } 2>&1 | tee stderr; } 3>&1 | tee stdboth
        exit
fi
# rest of your script here
_

teeはラインバッファリングを使用しないため(stdbuf(1)を使用して強制することもできません)、stdoutとstderrに書き込まれるデータの順序は最終出力では考慮されません。フルバッファリングを使用し、stdoutとstderrの両方に書き込むコマンドでは、ラインバッファリングteeは役に立たず、さらに悪いことに、出力行がstdoutとstderrの半分になる場合があります。

シェル言語とすぐに利用できるコマンドラインユーティリティを使用するだけで問題が解決することはないと思います。

2
mosvy

CI/CDライブラリを作成していますが、クライアントがライブラリを使用する目的がわからないので、それぞれの使用例を説明します。

これがシナリオであることを考えると、出力を処理するためのbashの必要性について質問します。このコンテキストで理想的には、出力にタイムスタンプを付けて標準出力タイプのIDを指定し、アプリケーションがメッセージの処理方法を決定するアプリケーションである必要があります。

1
Braiam