Bash
保存退出程式碼以備後用
所以我有一個小腳本來執行一些測試。
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 或一般的 shell 中)?
我會去:
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
據我所知,bash 與
try...finally
更像 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 )
請注意,括號分隔子外殼;使用這種結構,如果命令失敗,則只有子shell 退出,而不是整個腳本。請記住,子shell 在計算上有些昂貴,因此不要使用太多(數百個)子shell。根據您的腳本,您可以使用 shell 函式和 更有效地實現相同的效果
trap ... RETURN
,但這取決於您進行調查。