背景
bash 3、4、5でそれぞれ次のコードを実行すると、他の結果が表示されます。
(function handle_error () { echo ERROR; }; trap handle_error ERR; (exit 1))
(exit 1)
呼び出したコマンドが失敗する可能性があると想像してください。この場合は常に失敗しますが、それは問題ではありません。handle_error
ゼロ以外の終了コードで終了したときに呼び出されることを望みます。マニュアルによると、これが正確にすtrap handle_error ERR
べきことです。
質問
bashバージョン3を使用するローカルシステムとはまったく異なるオペレーティングシステムに、bashバージョン4を使用するリモートシステムがあります。
- bash 3.2.57(1), 3.2.48(1): 出力を返しません。
man bash
組み込みからの抜粋trap
:sigspecがERRの場合、単純コマンドの終了状態がゼロでないたびに、次の条件に従ってargコマンドが実行されます。
- bash 4.4.23(1), 4.4.12(1):
ERROR
期待どおりに印刷されます。man bash
組み込みからの抜粋trap
:sigspecがERRの場合、パイプライン(単一の単純なコマンドで構成できます)、リスト、または複合コマンドがゼロ以外の終了状態を返すたびに、次の条件に従ってargコマンドが実行されます。
- bash 5.0.2(1):
ERROR
期待どおりに印刷されます。
ドキュメントを見ると、両方のバージョンが同じように機能する必要があると思いますが、そうではありません。
Freenodeにログインして、この動作がすべてのメジャーバージョン3、4、5で同じであることを確認しました。ただし、メジャーバージョンを指定できる#bash
シェルボット(ニックネーム)が異なります。shbot
このシェルボットは、私が試した2つのシステムとは異なるオペレーティングシステムで実行されており、私がアクセスできる同じbashメジャーバージョンと比較した場合、マイナーバージョンも異なります。
質問
誰かがbashバージョン3、4、5でこの動作が異なる理由を説明する信頼できるソースを指摘できますか?私はこれが間違いだと信じるのは難しいです。恋しくなる理由がまたあると思います。
ベストアンサー1
これはBash 3.2のバグのように見えます。
アイテムが見つかりません。変更ログこれは直接一致します。 POSIX合意(bash-4.0-rc1からbash-4.0-releaseに変更されるプロジェクト)errexit
と一致するようにオプションの動作を変更することについてのあいまいな言及しかありません。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