だから、いくつかのテストを実行する小さなスクリプトがあります。
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...finally
bashが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...finally
Cのブロックのように機能するかなり一般的なイディオムに置き換えることができます。次のように:
(
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)