保存退出代码以备后用


15

因此,我有一个用于运行某些测试的小脚本。

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)?

Answers:


5

您可以将exitand rm命令包装成一个简单的命令,eval例如:

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

这样$?,传递给时的值exit就是在eval运行前立即分配的值。


eval一直是粉丝的最爱。
mikeserv

23

我会去:

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

嗯,我同意这比我的原版要好。但是我仍然不能令人满意地将退出代码显式存储到变量中。是否没有办法“推送”退出代码并稍后再次“弹出”?
math4tots 2015年

@ math4tots尝试更新。
muru

因此,在进行更新时,我将必须将last_error_code初始化为零,然后在最后返回,这样,如果有任何命令抛出错误,我将获得非零的退出代码?这是一个很酷的技巧,但是对于我的两行hack脚本,我想我更喜欢@mikeserv的答案。
math4tots

@ math4tots您可以随时这样做exit ${last_error_code:=0}
muru

@avip做什么用?它已经用单引号引起来,因此仅在调用陷阱时才评估变量。
muru

9

据我所知,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函数和来更有效地达到相同的效果trap ... RETURN,但这取决于您自己进行研究。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.