Bash

保存退出程式碼以備後用

  • February 13, 2022

所以我有一個小腳本來執行一些測試。

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...finallyC 中的一個塊。像這樣:

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

請注意,括號分隔子外殼;使用這種結構,如果命令失敗,則只有子shell 退出,而不是整個腳本。請記住,子shell 在計算上有些昂貴,因此不要使用太多(數百個)子shell。根據您的腳本,您可以使用 shell 函式和 更有效地實現相同的效果trap ... RETURN,但這取決於您進行調查。

引用自:https://unix.stackexchange.com/questions/178539