次のbashスクリプト版画「これは実行することはありません!」:ブール関数はブール式で呼び出されたときにエラーを無視しますか?
#!/bin/bash
set -e
func() {
echo "Bailing out..."
false # Should bail out because of set -e
echo "This should never run!"
}
func || true
ここで何が起こっていますか?
簡単な結論は、set -e
が関数内に伝播しないということです。しかし、そうではありません。最後の行(func || true
)をちょうどfunc
に変更すると、関数は期待通りにfalse
ステートメントで停止します。
もう一つの仮説は、bashが機能の実行を開始しますし、最初のエラーで(false
は)それを、そのretuns 0(真)場合には(func || true
)に呼ばれた行の残りの部分を評価し、あたかも何も起こらないかのように関数の実行を続けます。しかし、true
をecho "Oops!"
に置き換えると、「おっと!印刷されます。
ブール式の一部として関数を実行すると、set -e
は何とか無視されますか? set -e
に関するman bash
から
文書化、予想される動作。 'set -e'はコーナーケースの**完全**です。そして、多くのサークルでは、それは価値があるよりも多くの問題を考慮しました。 http://mywiki.wooledge.org/BashFAQ/105、http://fvue.nl/wiki/Bash:_Error_handling、http://wiki.bash-hackers.org/scripting/obsolete〜を参照してください。 * set -e機能は、他のすべての機能を組み合わせたものより多くの質問とバグ報告をBashメーリングリストで生成します!* –
...ところで、ちょっと意地悪に触れる - check_something | | 'check_something'が失敗した場合、do_somethingは終了しません。もしそうなら、それは 'set -e'を意味し、分岐操作はお互いに互換性がありません。残念なことに、この仕様は十分にわかりませんでした。なぜなら、私たちが終わったのは、 'set -e'が完全に無効になってスタックのどこにいても、実行中の操作の結果がブランチに使用されるというケースです。それがPOSIXによって指定され、準拠している既存のシェルによって尊重されているので、その動作は大規模な互換性の問題なしに修正することはできません。 –
[個人的には、 'set -e'とブランチング操作*がスタックフレームごとのフラグである限り、実際には互いに互換性がないならば、もっとうまくいくと主張します。それは明示的にオンにする必要があることを意味します。 (関数の外にあるときは '|| exit')、後でオフに戻りますが、少なくともその動作は一貫性があり明白であり、監査するのが容易です]。 –