2016-07-01 4 views
1

次の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)に呼ばれた行の残りの部分を評価し、あたかも何も起こらないかのように関数の実行を続けます。しかし、trueecho "Oops!"に置き換えると、「おっと!印刷されます。

ブール式の一部として関数を実行すると、set -eは何とか無視されますか? set -eに関するman bashから

+2

文書化、予想される動作。 '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メーリングリストで生成します!* –

+0

...ところで、ちょっと意地悪に触れる - check_something | | 'check_something'が失敗した場合、do_somethingは終了しません。もしそうなら、それは 'set -e'を意味し、分岐操作はお互いに互換性がありません。残念なことに、この仕様は十分にわかりませんでした。なぜなら、私たちが終わったのは、 'set -e'が完全に無効になってスタックのどこにいても、実行中の操作の結果がブランチに使用されるというケースです。それがPOSIXによって指定され、準拠している既存のシェルによって尊重されているので、その動作は大規模な互換性の問題なしに修正することはできません。 –

+0

[個人的には、 'set -e'とブランチング操作*がスタックフレームごとのフラグである限り、実際には互いに互換性がないならば、もっとうまくいくと主張します。それは明示的にオンにする必要があることを意味します。 (関数の外にあるときは '|| exit')、後でオフに戻りますが、少なくともその動作は一貫性があり明白であり、監査するのが容易です]。 –

答えて

4

終了直ちにパイプライン(単一の単純な命令から成ることができる)、リスト、または化合物のコマンドであれば(上記シェルの文法を参照)、非で終了ゼロ状態。 失敗したコマンドが、whileまたはuntilキーワードの直後のコマンドリストの一部である場合、シェルはを終了しません。ifまたはelif予約語に続くコマンドの一部は、& &または| |リストの最後の次のコマンドを除く& &または||、パイプライン内の任意のコマンドが最後のコマンド、またはコマンドの戻り値が反転されている場合は! -eが無視されている間にコマンドが失敗したため、サブシェル以外の複合コマンドが0以外のステータスを返した場合、シェルは終了しません。 ERRのトラップが設定されていると、シェルが終了する前に実行されます。このオプションはシェル環境と各サブシェル環境に別々に適用され(上記のコマンド実行環境を参照)、サブシェル内のすべてのコマンドを実行する前にサブシェルを終了させる可能性があります。

+0

ありがとうございます。簡単な回避策はありますか?私はサブシェル( '(func)|| true')で関数を実行しようとしましたが、それもうまくいきませんでした。 –

+0

私が正しく理解するならば、 'set -e'は、関数にゼロ以外の値を"返す "ことはできず、代わりにスクリプトを実行させ続けるか、スクリプト全体を完全に停止させるだけですか? –

+0

@VladimirPanteleev - 修正してください。 'set -e'は単純に' ||関数を呼び出すたびに$?を返します。それは、メインスクリプトが正常に実行されるか、または完全に実行されるようにします。関数の戻り値を制御する必要がある場合は、それを自分で管理する必要があります。 –

関連する問題