`{ { (exit 1); exit 1; }; }` はどういう意味ですか?

`{ { (exit 1); exit 1; }; }` はどういう意味ですか?

次のコード スニペットはconfig.statusgenerated byから引用しましたconfigure

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

答え1

実行は、トラップ(exit 1);をトリガーする最も簡単な方法です。が有効なERR場合は、即時終了もトリガーします。(エラー状態をトリガーするには、コマンドが失敗する必要があります。サブシェルに失敗値があると、サブシェルが失敗します。)set -eexit

exit 1;どちらも行いません。

したがって、最初にトラップを生成してデバッグの目的に役立つ何かを実行し、その後エラーを表示してスクリプトを終了する{(exit 1); exit 1;}ために使用できます。ERR

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

しかし、どうやら一部のシェルは協力しないようです。以下はautoconfマニュアル:

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

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

回避策は、$?終了ステータスが前にコマンドexitが実行されると、トラップが実行されたときにその値が確実に保持されます。実際、冗長な中括弧を含む奇妙なコードを挿入するのはマクロEXITです。AC_MSG_ERROR

答え2

私の知る限り、これには目的がなく、サブシェルを起動してすぐに終了することで直接達成できるものは何もありません。

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

の多用も{...}この例の 1 つです。そのほとんどは冗長ですが、不要なものを区別して省略するよりも、あらゆる場合にそれらを挿入するコード (ブロックの出力/入力をリダイレクトしたい場合もあるでしょう) を記述する方が簡単です。

答え3

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

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

関連情報