web-dev-qa-db-ja.com

コマンド出力をティーにパイピングするが、コマンドの終了コードも保存する

出力をログファイルにリダイレクトするコマンド(mvn clean install)をラップするシェルスクリプトがあります。

#!/bin/bash
...
mvn clean install $@ | tee $logfile
echo $? # Does not show the return code of mvn clean install

mvn clean installがエラーで失敗した場合、ラッパーシェルスクリプトもそのエラーで失敗するようにします。しかし、すべての出力をteeにパイプしているため、mvn clean installの戻りコードにアクセスできません。したがって、$?にアクセスすると、常に0になります(teeが成功するため)。

コマンドにエラー出力を別のファイルに書き込ませ、その後チェックすることを試みましたが、mvnのエラー出力は常に空です(stdoutにのみ書き込むようです)。

mvn clean installのリターンコードを保持しながら、出力をログファイルにパイプする方法はありますか。

143
Ingo Fischer

bashを実行しているため、$?の代わりに $ PIPESTATUS 変数を使用できます。

mvn clean install $@ | tee $logfile
echo ${PIPESTATUS[0]}
136

pipefailシェルオプション オプションをオンに設定して、必要な動作を取得できます。

Bash Reference Manual から:

pipefailオプションが有効になっていない限り、パイプラインの終了ステータスは、パイプラインの最後のコマンドの終了ステータスです( The Set Builtin を参照)。 pipefailが有効な場合、パイプラインの戻りステータスは、ゼロ以外のステータスで終了する最後の(右端)コマンドの値、またはすべてのコマンドが正常に終了した場合はゼロです。

例:

$ false | tee /dev/null ; echo $?
0
$ set -o pipefail
$ false | tee /dev/null ; echo $?
1

元のパイプ設定を復元するには:

$ set +o pipefail
181

Mvnコマンドを実行して終了コードをキャッシュすることができます...私の例では「false」コマンドを使用します。

$ { false ; echo $? > /tmp/false.status ; } | tee $logfile
$ cat /tmp/false.status
1

そうすれば、ステータスファイルの内容を使用して、さらに決定を下すことができます。

私は今、これを達成するためのより雄弁な方法があるかどうか興味があります。

11
Demosthenex

回避策(注:@Fredericのperferのソリューション):

f=`mktemp`
(mvn clean install $@; echo $?>$f) | tee $logfile
e=`cat $f` #error in variable e
rm $f
3
Karoly Horvath