次のコードをbash3、4、5でそれぞれ実行すると、異なる結果が得られます。
(function handle_error () { echo ERROR; }; trap handle_error ERR; (exit 1))
(exit 1)
が、失敗する可能性のある呼び出すコマンドであると想像してください。この場合、それは常に失敗しますが、それは実際には問題ではありません。ゼロ以外の終了コードで終了するときにhandle_error
が呼び出されるようにします。マニュアルによると、これはまさにtrap handle_error ERR
がすべきことです。
Bash 3のバージョンのローカルシステムと、bash4のバージョンのまったく異なるオペレーティングシステムのリモートシステムがあります。
trap
ビルトインのman bash
からの抜粋:SigspecがERRの場合、次の条件に従って、単純なコマンドの終了ステータスがゼロ以外の場合は常にコマンドargが実行されます。
ERROR
を出力します。 trap
ビルトインのman bash
からの抜粋:SigspecがERRの場合、次の条件に従って、パイプライン(単一の単純なコマンドで構成されている場合があります)、リスト、または複合コマンドがゼロ以外の終了ステータスを返すたびに、コマンドargが実行されます。
ERROR
を出力します。ドキュメントから、動作は両方のバージョンで同じである必要があると思いますが、そうではありません。
Freenodeで#bash
にログオンし、シェルボット(ニックshbot
)を使用して、この動作がすべてのメジャーバージョン3、4、5で同じように異なることも確認しました。メジャーバージョンを指定します。このシェルボットは、私が試した両方のシステムとは異なるオペレーティングシステムで実行され、アクセスできる同じメジャーバージョンのbashとは異なるマイナーバージョンが使用されています。
この動作がbashのバージョン3、4、および5と異なる理由を説明する信頼できる情報源を誰かが指摘できますか?これがバグだとは信じがたいです。私が見逃している別の理由があるに違いありません。
これはBash3.2のバグのようです。
changelog に、それに直接一致するエントリが見つかりません。 POSIXコンセンサスに一致するようにerrexit
オプションの動作を変更することについては漠然とした言及しかありません(bash-4.0-rc1からbash-4.0-releaseへの変更の項目l
)。
errexit
にも同様の問題があるため、これはBash 3.2ではトリガーされませんが、Bash 4.0ではトリガーされます(サブシェルコマンドが失敗するとシェルが終了するため、何も出力されないはずです)。 :
$ ./bash3.2 -c 'set -e; (exit 1); echo end.'
end.
これは両方のバージョンで機能するため、ここでの問題はサブシェルのように見えることに注意してください。
$ ./bash3.2 -c 'trap "echo ERROR" ERR; false'
ERROR