2011-03-15 65 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變量存在的測試,所以我甚至不需要在腳本的開始處設置它。