後で使用できるように終了コードを保存

後で使用できるように終了コードを保存

だから、いくつかのテストを実行する小さなスクリプトがあります。

javac *.java && java -ea Test
rm -f *.class

これで問題は、スクリプトの実行時に./testテストが失敗してもrm -f *.class成功したため、成功した終了コードを返すことです。

私が望むことを行うために私が考えることができる唯一の方法は私に醜い感じです。

javac *.java && java -ea Test
test_exit_code=$?
rm -f *.class
if [ "$test_exit_code" != 0 ] ; then false; fi

しかし、これは一般的な問題のようです。ジョブを実行してクリーンアップし、元のジョブの終了コードを返します。

これを行う最も慣用的な方法は何ですか(bashまたは通常シェルで)。

答え1

私は以下を選択します:

javac *.java && java -ea Test
test_exit_code=$?
rm -f *.class
exit "$test_exit_code"

exit利用可能なのに、なぜジャンプしますか?


あなたが使用できるtrap

trap 'last_error_code=$?' ERR

たとえば、

$ trap 'last_error_code=$?' ERR
$ false
$ echo $?
1
$ echo $last_error_code $?
1 0

答え2

私が知る限り、try...finallybashがCに似たプログラミング言語(ある場合は望むかもしれません)に最も近いのは、trap次のように動作するコンストラクタです。

trap "rm -f *.class" EXIT
javac *.java && java -ea Test

スクリプトが終了すると、「rm -f *.class」が実行されます。より複雑な作業を行う必要がある場合は、関数に入れることができます。

cleanup() {
    ...
}
trap cleanup EXIT
javac *.java && java -ea Test

必要に応じて、これを約try...catch...finallyCのブロックのように機能するかなり一般的なイディオムに置き換えることができます。次のように:

(
  trap "catch_block; exit" ERR
  trap finally_block EXIT
  # contents of try goes here
)

この構成では、角かっこでサブシェルを区切ります。コマンドが失敗すると、スクリプト全体ではなくサブシェルのみが終了します。サブシェルは計算コストがやや高価なので、あまりにも(数百)使用しないでください。スクリプトによってはシェル機能を使用し、同じ効果をより効率的に得ることができますが、trap ... RETURNこれは研究によって異なります。

答え3

exitコマンドをrm次の簡単なコマンドでラップできますeval

java ... && java ...
eval "rm -f *.class; exit $?"

way$?に渡される値は、exit実行直前に割り当てられた値です。eval

答え4

アプローチを少し面倒にするには、exitサブシェルで次を使用します。

javac *.java && java -ea Test
test_exit_code=$?
rm -f *.class
(exit $test_exit_code)

関連情報