[英]How to trap ERR when using 'set -e' in Bash
我有一個簡單的腳本:
#!/bin/bash
set -e
trap "echo BOO!" ERR
function func(){
ls /root/
}
func
如果我的腳本失敗,我想捕獲 ERR(因為它會在這里 b/c 我沒有查看 /root 的權限)。 但是,當使用set -e
時,它不會被困住。 沒有set -e
ERR 被困。
根據 bash 手冊頁,對於set -e
:
...如果設置了 ERR 陷阱,則會在 shell 退出之前執行。 ...
為什么我的陷阱沒有被執行? 從手冊頁看來應該如此。
chepner 的答案是最好的解決方案:如果要將set -e
(與set -o errexit
相同)與ERR
陷阱結合使用,還可以使用set -o errtrace
(與set -E
相同) 。
簡而言之:使用set -eE
代替set -e
:
#!/bin/bash
set -eE # same as: `set -o errexit -o errtrace`
trap 'echo BOO!' ERR
function func(){
ls /root/
}
# Thanks to -E / -o errtrace, this still triggers the trap,
# even though the failure occurs *inside the function*.
func
一個更復雜的示例trap
示例,以紅色打印消息並打印退出代碼: trap 'printf "\\e[31m%s: %s\\e[m\\n" "BOO!" $?' ERR
man bash
關於set -o errtrace
/ set -E
:
如果設置,則 ERR 上的任何陷阱都由 shell 函數、命令替換和在子 shell 環境中執行的命令繼承。 在這種情況下,ERR 陷阱通常不會被繼承。
我相信正在發生的事情:
沒有-e
: ls
命令在您的函數內失敗,並且由於是函數中的最后一個命令,該函數將ls
的非零退出代碼報告給調用者,即您的頂級腳本范圍。 在該范圍內, ERR
陷阱生效並被調用(但請注意,執行將繼續,除非您顯式地從陷阱中調用exit
)。
隨着-e
(但沒有-E
)的ls
命令自己的函數中失敗,因為set -e
生效,猛砸立即退出,直接從功能范圍-而因為沒有ERR
陷阱效應存在(因為它不是從父作用域繼承的),則不會調用您的陷阱。
雖然man
頁並沒有錯,但我同意這種行為並不完全明顯 - 您必須推斷它。
您需要對函數使用set -o errtrace
來繼承陷阱。
用EXIT
替換ERR
它將起作用。
trap
命令的語法是: trap [COMMANDS] [SIGNALS]
有關更多信息,請閱讀http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_02.html
我們有這些調試選項:
-e
失敗立即退出-E
如果設置,ERR 上的任何陷阱都由 shell 函數繼承-u
存在未綁定變量時退出-o
給出要設置的選項名稱
-v
在讀取時打印所有 shell 輸入行-x
打印命令跟蹤為了處理錯誤,我們可以使用trap捕獲目錄
trap 'echo >&2 "Error - exited with status $? at line $LINENO' ERR
或者更好的版本ref :
trap 'echo >&2 "Error - exited with status $? at line $LINENO:";
pr -tn $0 | tail -n+$((LINENO - 3)) | head -n7' ERR
或 function:
function __error_handing__(){
local last_status_code=$1;
local error_line_number=$2;
echo 1>&2 "Error - exited with status $last_status_code at line $error_line_number";
perl -slne 'if($.+5 >= $ln && $.-4 <= $ln){ $_="$. $_"; s/$ln/">" x length($ln)/eg; s/^\D+.*?$/\e[1;31m$&\e[0m/g; print}' -- -ln=$error_line_number $0
}
並這樣稱呼它:
trap '__error_handing__ $? $LINENO' ERR
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.