set -e
(errexit
)、set -u
(nounset
)とともにERRおよびEXITトラップを使用すると、奇妙な動作が見られます。それらは関連しているように見えるので、それらを1つの質問に入れるのは合理的です。
1)set -u
ERRトラップをトリガーしません
コード:
#!/bin/bash trap 'echo "ERR (rc: $?)"' ERR set -u echo ${UNSET_VAR}
- 予期:ERRトラップが呼び出されます。RC!= 0
- 実際:ERRトラップは呼び出されません、RC == 1
- 注:
set -e
結果は変わりません
2)set -eu
EXITトラップでの終了コードの使用は1ではなく0です
コード:
#!/bin/bash trap 'echo "EXIT (rc: $?)"' EXIT set -eu echo ${UNSET_VAR}
- 予期:EXITトラップが呼び出されます、RC == 1
- 実際:EXITトラップが呼び出され、RC == 0
- 注:を使用する
set +e
場合、RC == 1です。他のコマンドがエラーをスローすると、EXITトラップは適切なRCを返します。 - 編集:このトピックには、使用されているBashバージョンに関連している可能性があることを示唆する興味深いコメントを含むSO投稿があります。このスニペットをBash 4.3.11でテストすると、RC = 1になります。残念ながら、現時点ではすべてのホストでBashを(3.2.51から)アップグレードすることはできないため、他のソリューションを考え出す必要があります。
誰もこれらの行動のいずれかを説明できますか?
これらのトピックの検索はあまり成功しませんでした。Bashの設定とトラップに関する投稿の数を考えると、これはかなり驚くべきことです。ある1つのフォーラムのスレッドはいえ、しかし、結論は、むしろ不満足です。
set -e
そしてset -u
両方のために特別に設計されて殺すスクリプトシェルを。う彼らのアプリケーショントリガする可能性がある状況でそれらを使用して殺すスクリプトシェルを。それらを使用せず、代わりにコードシーケンスで適用するときにそれらの条件をテストすることを除いて、それを回避することはできません。したがって、基本的には、適切なシェルコードを記述するか、を使用できますset -eu
。
-u
は、ERRトラップをトリガーしない理由に関する十分な情報を見つけることができなかったためです(エラーであるため、トラップをトリガーするべきではありません)、またはエラーコードは1ではなく0です。後者は、後のバージョンですでに修正されているバグのようですので、それだけです。しかし、シェル評価(パラメーター展開)のエラーとコマンドの実際のエラーが2つの異なるものであることに気付いていない場合、最初の部分を理解するのは非常に困難です。解決策については、あなたが提案したように、-eu
必要なときに手動で回避して確認しようとしています。
(set -u; : $UNSET_VAR)
。この種のものも良いことがあります- 私のドリフトを取得する場合、あなたは&&
時々多くのものをドロップすることができます:(set -e; mkdir dir; cd dir; touch dirfile)
。それらが制御されたコンテキストであるというだけです-それらをグローバルオプションとして設定すると、制御を失い、制御されます。ただし、通常はより効率的なソリューションがあります。
bash
、標準を破り、サブシェルにトラップを入れ始めたと思います。トラップは、どこから戻ってきたかと同じ環境で実行されることになっていますが、bash
しばらくは実行されていません。