現在の環境を修正する関数の標準エラーをキャプチャする方法は?

現在の環境を修正する関数の標準エラーをキャプチャする方法は?

module機能環境モジュール1パッケージはさまざまな環境変数を変更して作業を行います。現在のシェルプロセス

残念ながら、この関数は成功したかどうかにかかわらず0 2を返すので、クライアントスクリプトは失敗に適切に対応するのが困難です。

すべてのパラメータを直接渡し、失敗時にゼロ以外の値を正しく返すmymodule関数ラッパーを実装したいと思います。modulemodulemodule

mymodule失敗を検出する唯一の方法は、module出力module関数がstderr(存在する場合)に何を書き込むかを確認することです。

問題は、ジョブをmymoduleキャンセルしないと、この出力を得るための合理的な方法を考えることができないことです。より具体的には、stderrを変数としてキャプチャするmoduleために私が考えることができるほとんどすべての方法は子プロセスで実行する必要があります。modulemodule

上記の例外はstderrを一時ファイルにリダイレクトすることですが、関数が実行されるたびにファイルを生成するという考えはmodule嫌いです。module

現在の環境でmymodule呼び出すmoduleと同時に変数に標準エラーをキャプチャする方法はありますか?

zsh私は両方の答えに興味がありますbash


1.交流しないでください。Lmod環境モジュールインターフェイスは非常に似たパッケージです。

2少なくとも私が使用しなければならなかった以前のバージョン3.2.9の場合はそうでした。私はこれを制御できません。

ベストアンサー1

Bashとzshの両方共同プロセス(残念ながら少し異なります)基本的には次のように終わります。pipe電話そして、呼び出しシェルで標準入力と標準出力を使用できるサブプロセスを作成します。デフォルトでは、シェルは現在のプロセスで実行されますが、xすべて、実行されます。yx | cmd | yxycmdいいえパイプライン実行環境で。

module 2>&...これにより、現在のシェルで何かを実行できます。セカンダリプロセスとして使用すると(たとえば)、すべてを直接再度繰り返し、後で出力を現在のシェルに読み直すことができます。...modulecatcmdy <&...

別のオプションは、標準エラーを別のバックグラウンドプロセスにリダイレクトし、対応するwait戻りコードを取得することです。以下では、これら2つの問題について議論します。


この偽の機能をテスト用に使用して、勝手にエラーをオン/オフmoduleできるようにします。 ifは私たちが見ることができるように現在のシェル環境を変更し、stderrに "err"を印刷します。必要に応じてこの行に注釈を付けます。

module() {
        sleep 1
        FOO=$(date)
        echo err >&2
} 

catBash で共同プロセスを実行すると、moduleの stderr をその中にリダイレクトし、catの stdout から読み込んで目的のタスクを実行できます。

coproc cat
module 2>&${COPROC[1]}
exec {COPROC[1]}>&-
if grep -q err <&${COPROC[0]}
then
        echo got an error
else
        echo no error
fi

zshでは、次のようにする必要があります。

module 2>&p
exec 4<&p
coproc :
if grep -q err <&4

代わりに、途中で。

どちらの場合も、module現在のシェルでコマンドを実行し、そこからエラー出力を読み取ることができます。関数がif正常に返される可能性があります。

cat現在の実行環境で実行されている以外はすべていいえパイプラインなどの独立した環境を作成します。echo $FOO最後にこれを確認すると、module現在の環境で実行してから日付が更新されたことを確認できます。


または、バックグラウンドプロセスはすべての操作を実行できます。これはBashで動作します:

exec 2> >( if grep -q . ; then exit 7 ; else exit 0 ; fi )
PID=$!
module
exec 2>&-
wait $PID
echo $?

上記の内容は、トップレベルの子プロセスの内容を出力するか、または7戻りコードを使用して必要に応じて実行するように調整できます。プロセス置換が設定されていない0ため、zshではそうではありません。この問題は解決可能でなければなりませんが、試みを中止しました。$!一時ファイルの代わりに固定fifoもここで動作します。

この場合、両側からFD 2を保存して復元することもできます。

おすすめ記事