如何在Bash脚本退出之前运行命令?


119

如果Bash脚本具有set -e,并且脚本中的命令返回错误,那么如何在脚本退出之前进行一些清理?

例如:

#!/bin/bash
set -e
mkdir /tmp/foo
# ... do stuff ...
rm -r /tmp/foo

/tmp/foo即使其中一个命令... do stuff ...失败,我如何确保将其删除?

Answers:


193

这是使用陷阱的示例:

#!/bin/bash -e

function cleanup {
  echo "Removing /tmp/foo"
  rm  -r /tmp/foo
}

trap cleanup EXIT
mkdir /tmp/foo
asdffdsa #Fails

输出:

dbrown@luxury:~ $ sh traptest
t: line 9: asdffdsa: command not found
Removing /tmp/foo
dbrown@luxury:~ $

请注意,即使asdffdsa行失败,清除仍会执行。


11

bash联机帮助页(关于内置文件):

trap [-lp] [[arg] sigspec ...]
当shell接收到信号sigspec时,将读取并执行命令arg。

因此,如Anon。的回答所示,请trap在脚本的早期调用以在ERR上设置所需的处理程序。


运行help trap以查看内置的一些帮助。
Flimm 2014年

8

从参考set

-e

如果简单命令(请参阅3.2.1简单命令)以非零状态退出,则立即退出,除非失败的命令是直到或while循环的一部分,if语句的一部分,&&或||的一部分。列表,或者使用!反转命令的返回状态。如果设置了ERR,则会在外壳程序退出之前执行陷阱。

(强调我的)。


使用“ -e”时可能值得添加“ -E”,请参见vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail
Max Barraclough

3

shdevguydavid的答案的版本。

#!/bin/sh
set -e
cleanup() {
  echo "Removing /tmp/foo"
  rm  -r /tmp/foo
}
trap cleanup EXIT
mkdir /tmp/foo
asdffdsa #Fails

参考:shellscript.sh


POSIX让我笑。:)您也已链接到很棒的教学网站。
Cometsong
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.