web-dev-qa-db-ja.com

`{{(exit 1);とは1番出口; }; } `という意味ですか?

configureによって生成された_config.status_の次のコードスニペットを引用しました。

_if test ! -f "$as_myself"; then
{ { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
{ (exit 1); exit 1; }; }
fi
_

コードスニペットでは、{ (exit 1); exit 1; };は何をしますか?サブシェルでexitのみを行う目的は何ですか?

28
MS.Kim

_(exit 1);_の実行は、ERRトラップをトリガーする最も簡単な方法です。 _set -e_が有効な場合は、即時終了もトリガーします。 (エラー条件をトリガーするには、コマンドが失敗する必要があります。サブシェルに失敗値を指定したexitは、サブシェルが失敗する原因になります。)

_exit 1;_は、これらのどちらも行いません。

そのため、{(exit 1); exit 1;}を使用して、最初にERRトラップを生成できます。これは、デバッグの目的で役立つ場合があります。その後、エラーを表示してスクリプトを終了します。

しかし、それはautoconfファイルで起こっていることではありません。 autoconfスクリプトは、実行中に作成された一時ファイルをクリーンアップするためにEXITトラップに依存しています。 bashを含むほとんどのシェルは、exitトラップを呼び出す前に、EXITコマンドで提供された値からステータスを設定します。これにより、EXITトラップがエラーから呼び出されたか、正常終了から呼び出されたかを検出でき、トラップ操作の終了時に終了ステータスが正しく設定されていることを確認できます。

ただし、一部のシェルは連携しないようです。 autoconf manual からの引用は次のとおりです。

autoconfによって生成されるような一部のシェルスクリプトは、終了する前にトラップを使用してクリーンアップします。最後のシェルコマンドがゼロ以外のステータスで終了した場合、トラップもゼロ以外のステータスで終了するため、呼び出し元はエラーが発生したことを認識できます。

残念ながら、Solaris _/bin/sh_などの一部のシェルでは、終了トラップが終了コマンドの引数を無視します。これらのシェルでは、トラップはそれが単純な出口によって呼び出されたか、出口1によって呼び出されたかを判別できません。出口を直接呼び出す代わりに、この問題の回避策がある_AC_MSG_ERROR_マクロを使用します。

回避策は、_$?_の終了ステータスbeforeexitコマンドの実行を確認することです。これにより、EXITトラップが実行されます。そして、確かに、その不思議なコードを挿入するのは_AC_MSG_ERROR_マクロであり、余分な中括弧が付いています。

33
rici

私が見る限り、これの目的はありません。サブシェルを開始してすぐに終了することで直接達成できることはありません。

このようなことは、コードを自動的に生成することの副作用である可能性が高いです。場合によっては、サブシェルでexit 1を使用することが理にかなっている他のコマンドが実行されることがあります。最終的に、場合によっては機能を持たないステートメントを挿入できるようにすることで、生成コードが何らかの形で単純化され、毎回「クリーンなコード」を生成することがより複雑になる可能性が高くなります。それか、上記を生成したコードのどちらかが不十分に書かれているだけです:)

{...}の寛大な使用はこれの別の例です。それらのほとんどは冗長ですが、すべての場合にそれらを挿入するコードを書く方が簡単です(おそらく、ブロックの出力/入力をリダイレクトしたい場合があります)。それらが必要とされていないものを区別し、それらを省略するのではなく。

8
Graeme

(exit 1)は、特定の終了コードを取得するためのおそらく最も単純な方法です(1の特殊なケースでは、もちろんもっと簡単な方法があります)。ただし、この場合は終了コードが検査されないため、これは理由ではありません。

exitをサブシェルに配置する目的は、スクリプトを終了しないことです(ただし、特定の終了コードの生成にexitを使用します)。

1
Hauke Laging