2011-03-15 66 views
31

我的bash代码中有很多退出点。我需要做一些清理退出工作,所以我用陷阱添加回调退出这样的:如何在Bash脚本中捕获退出代码

trap "mycleanup" EXIT 

的问题是存在的是不同的退出代码,我需要做相应的清理工作。我可以在mycleanup中获得退出代码吗?

+0

trap'foo'EXIT或trap'foo'CHLD? –

回答

31

我想你可以使用$?来获得退出代码。

+1

是的,这是正确的。谢谢! – Dagang

+2

@Todd:变量'$ BASH_COMMAND'和'$ BASH_LINENO'有时也派上用场。 –

+4

@Todd,@bmk:不要忘记*任何执行的命令都会改变$的值。例如,myCmdIWantToTest; echo $? ; myRC = $? ; ...现在myRC是echo $的'真相'? cmd被调用。如果myCmdIWantToTest退出'false',则该值将丢失。最好节省$?到一个单独命名的var是唯一的。使用exitCode = $?通常情况下,您可以轻松结束继承其他cmd的exitCode(或更可能来自子shell(脚本))。另外,不要忘记,它可以测试退出代码作为if的一部分;然后 ; ... fi。就像myCmdIWantToTest;然后回声工作;其他回声失败;科幻 – shellter

25

接受的答案基本上是正确的,我只是想澄清事情。

下面的例子效果很好:

#!/bin/bash 

cleanup() { 
    rv=$? 
    rm -rf "$tmpdir" 
    exit $rv 
} 

tmpdir="$(mktemp)" 
trap "cleanup" INT TERM EXIT 
# Do things... 

但是你必须要,如果这样做清理直列更加谨慎,没有一个功能。例如,这将不起作用:

trap "rv=$?; rm -rf $tmpdir; exit $rv" INT TERM EXIT 

相反,你必须逃离$rv$?变量:

trap "rv=\$?; rm -rf $tmpdir; exit \$rv" INT TERM EXIT 

你可能也想逃离$tmpdir,因为它会得到评估时的陷阱线得到执行,如果tmpdir值稍后更改,将不会给您预期的行为。

编辑:使用shellcheck来检查你的bash脚本,并意识到这样的问题。

2

我发现它是从陷阱更好地独立出口俘获其它信号

例陷阱测试脚本...

umask 77 
tmpfile=`tmpfile.$$` 
trap 'rm -f "$tmpfile"' EXIT 
trap 'exit 2' HUP INT QUIT TERM 

touch $tmpfile 
read -r input 

exit 10 

临时文件清理。 保存10的文件出口值! 中断导致退出值为2

基本上,只要您不在EXIT陷阱中使用“退出”,退出时它将保留原始退出值。

ASIDE:注意EXIT陷阱中的引用。这让我可以在脚本生命周期中更改需要清理的文件。我经常也包含对$ tmpfile变量存在的测试,所以我甚至不需要在脚本的开始处设置它。