Bash: 出错时退出并清理

13
在我的Bash脚本中,我希望确保脚本一旦出现错误就立即退出。(例如,在执行失败的cd some_directory之后避免错误地使用rm -f *。)因此,我总是为bash使用-e标志。
现在,我还想在某些脚本中执行一些清理代码。从this blog post中我了解到:
#!/bin/bash

cd invalid_directory
echo ':('

function clean_up {
  echo "> clean_up"
  exit 0
}
trap clean_up EXIT

我得到的输出是
./test.sh: line 3: cd: invalid_directory: No such file or directory
:(
> clean_up

所以它做了广告中所说的事情。然而,当在bash中使用-e时,我只得到

./test.sh: line 3: cd: invalid_directory: No such file or directory

因此,该脚本在不调用 clean_up 的情况下退出。

我如何让Bash脚本在出现错误时退出,并每次调用清理脚本?


1
@NicoSchlömer 你尝试过 trap clean_up ERR 吗? - Biffen
@chepner,您介意详细说明一下吗?有什么好处呢? - Biffen
@Biffen 感谢你的提示。不幸的是,ERR并不能解决问题。 - Nico Schlömer
@NicoSchlömer,这对我有效。你能发布一个MCVE吗? - Biffen
可能是重复的问题:Bash:在脚本退出之前运行命令? - Calimo
显示剩余4条评论
1个回答

28

在配置trap之前,你永远无法达到trap命令;因为shell在配置trap之前就已经退出了。

set -e
clean_up () {
    ARG=$?
    echo "> clean_up"
    exit $ARG
} 
trap clean_up EXIT
cd invalid_directory
echo "Shouldn't reach this"

然而,最好还是自己处理错误。你通常希望根据脚本退出的确切原因来变化行为,如果你为所有退出运行单个处理程序(即使将陷阱限制为ERR而不是EXIT),这样做会更加复杂。

cd invalid_directory || { echo "cd to invalid_directory failed" >&2; exit 1; }
echo "Shouldn't reach this"

这并不意味着你必须放弃你的clean_up函数。它仍然会在显式退出时执行,但它应该被限制在无论为什么原因你的脚本退出时都应该运行的代码上。你还可以在ERR上设置陷阱,以执行只有在你的脚本以非零退出状态退出时才执行的代码。


看起来你(楼主)想要使用 cd invalid_directory || exit。只是确认一下 - 否则,每次都会到达“不应该到达这里”。 - David C. Rankin
这就是我真正会做的事情(请看我在问题上的评论)。我只是指出为什么退出处理程序没有执行。不过我会用那种方法来更新。 - chepner
1
我也是这么想的,但看到“不应该到达此处”的那一行时,我只是摸不着头脑。 - David C. Rankin
哦,我忘记了说明代码是在运行 set -e 的情况下的 :) - chepner
感谢@chepner的出色回答!您知道在“EXIT”上是否可以将退出代码设置为0,而在“ERR”上设置为1吗? - Nico Schlömer
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接