簡単なスクリプトがあります:
#!/bin/bash
set -e
trap "echo BOO!" ERR
function func(){
ls /root/
}
func
スクリプトが失敗した場合に ERR をトラップしたいと思います (/root を調べる権限がないため、ここでは失敗します)。ただし、使用している場合はset -e
トラップされません。使用しない場合はset -e
ERR がトラップされます。
bash のマニュアルページによるとset -e
、
... ERR のトラップが設定されている場合は、シェルが終了する前に実行されます。...
なぜトラップが実行されないのですか? man ページによると、実行されるはずです。
ベストアンサー1
チェプナーの答え最善の解決策です: あなたが望むなら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 のすべてのトラップは、シェル関数、コマンド置換、およびサブシェル環境で実行されるコマンドによって継承されます。通常、このような場合には ERR トラップは継承されません。
私が信じていることは次のとおりです。
それなし
-e
:ls
コマンドは関数内で失敗し、関数内の最後のコマンドであるため、関数はls
呼び出し元、つまりスクリプトの最上位スコープに の非ゼロ終了コードを報告します。その範囲、ERR
トラップは有効になり、呼び出されます (ただし、exit
トラップから明示的に呼び出さない限り、実行は続行されることに注意してください)。と
-e
(ただし、 なし-E
):ls
コマンドは失敗する関数内で、そしてset -e
が有効であるため、Bash即座に出口、関数スコープから直接- そしてERR
罠は効いていないのでそこには(親スコープから継承されていないため)、トラップは呼び出されません。
ページは間違ってはいませんがman
、この動作は必ずしも明白ではなく、推測する必要があることに同意します。