web-dev-qa-db-ja.com

後で使用するために終了コードを保存

だから私はいくつかのテストを実行するための小さなスクリプトを持っています。

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または単に一般的にシェルで)?

15
math4tots

次のように、exitコマンドとrmコマンドをevalを使用して単一の単純なコマンドにラップできます。

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

このようにして、exitに渡されたときの$?の値は、evalが実行される直前に割り当てられる値です。

5
mikeserv

私は一緒に行きます:

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
23
muru

私が知る限り、bashがよりCに似たプログラミング言語からのtry...finallyブロックに最も近いもの(これがおそらく使用可能であれば必要なものです)はtrap構造です。このように動作します:

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

これにより、スクリプトの終了時に「rm -f * .class」が実行されます。もっと複雑なことがあれば、それを関数に入れることができます:

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

もしそうしたいと思うなら、これをCのtry...catch...finallyブロックのように機能するかなり一般的なイディオムに変えることができます。このようなもの:

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

括弧はサブシェルを区切ることに注意してください。この構成では、スクリプト全体ではなく、コマンドが失敗した場合にサブシェルのみが終了します。サブシェルはいくぶん計算コストが高いので、サブシェルをあまり多く(数百)使用しないでください。スクリプトによっては、シェル関数とtrap ... RETURNを使用して同じ効果をより効率的に達成できる場合がありますが、調査するのはあなた次第です。

10
David Z