出力を別のプロセスにパイプしながら、最初のプロセスのエラー状態を維持する方法は? [コピー]

出力を別のプロセスにパイプしながら、最初のプロセスのエラー状態を維持する方法は? [コピー]

重複の可能性:
別のプロセスにパイプされた終了コードを取得する

私は、次のコマンドライン(makefileから)を使用して、人間が読める内容に減らすPerlスクリプトを介してコンパイラの詳細なエラーメッセージを渡します。

g++ -c source.cpp -o source.o 2>&1 | perl /bin/gSTLFilt.pl

残念ながら、このアプローチはコマンドから返されたエラー値を「マスク」しますg++。 makeはコマンドのエラー結果g++のみを返すので、コマンドが失敗したことを知りません。perl

出力をパイプして元のエラー状態を維持する方法はありますか?

違いがある場合:私はGNU bashバージョン2.04.0(1)-リリース(i686-pc-)を実行しているMSYSコンソールでGNU Make 3.81とg ++(GCC)3.4.5(mingw-vistaspecial r3)を使用しています。 msys)(Windows XP)。

答え1

sh.exeWindows実行可能ファイルにその名前を使用する複数のシェルがあるため、シェルが何を提供しているのかわかりませんが、bash似ているか似ている場合は配列を使用できます$PIPESTATUS。あなたの例は次のようにすることができます:

g++ -c source.cpp -o source.o 2>&1 | perl /bin/gSTLFilt.pl
echo "${PIPESTATUS[0]}"

答え2

Bashには次のオプションがありますpipefail

The return status of a pipeline is the exit status of the last command,
unless  the  pipefail  option  is enabled.  If pipefail is enabled, the
pipeline's return status is the value of the last  (rightmost)  command
to  exit  with a non-zero status, or zero if all commands exit success-
fully.

だから:

set -o pipefail && $GCC_COMMAND | $PERL_COMMAND

Makeは各行に対してサブシェルの各行を実行します。したがって、gcc行の先頭に追加する必要があります。 set を使って make に 1 つのコマンドだけを実行させる方法があるかもしれませんが、pipefailよく分かりません。

SHELL=/bin/bashクリエイターはこれを使用する必要があります)

または、次のことを試してください。

bash -o pipefail -c "$GCC_COMMAND | $PERL_COMMAND"

答え3

既存のシェルでは、パイプラインの最初のコマンド状態はスクリプトにまったく報告されません。では、最後のコマンドの状態のみを使用できます$?

バッシュ≥3.0では、パイプラインのどこでもエラーが発生した場合は、停止したい場合にこのpipefailオプションを使用してください。

g++ -c source.cpp -o source.o 2>&1 | perl /bin/gSTLFilt.pl

より一般的には、Bashでは、配列はPIPESTATUS最後の$?パイプラインのすべてのコマンドを含むように一般化されています。

$ (exit 1) | (exit 2) | (exit 3); echo ${PIPESTATUS[@]}
1 2 3

Zshにも同じ機能がありますが、配列を呼び出しますpipestatus

% zsh -c '(exit 1) | (exit 2) | (exit 3); echo $pipestatus'    
1 2 3

bash(IIRCはmsysが提供するシェル)を使用したい場合はshそれを使用できますPIPESTATUS。そうでない場合は、終了状態を最上位シェルにパイプし、フィルタプログラムを終了させることができます。入力の最後の行を読み取り、通常の入力として使用する代わりに終了するステータスを取得します。あいまいですが便利です。

メイクファイルでは、コンパイラメッセージが別の中間ファイルとして扱われる一時ファイルを使用するのが比較的一般的です。

%.otmp %.g++-log: %.cpp
        g++ -c $< -o $@tmp 2>&1 >$*.g++-log
%.o: %.otmp %.g++-log
        perl /bin/gSTLFilt.pl <$*.g++-log
        mv $*.otmp $@

関連情報