Linuxの終了コードの最小値と最大値は何ですか?


40

Linuxの次の終了コードの最小値と最大値は何ですか?

  1. バイナリ実行可能ファイル(Cプログラムなど)から返された終了コード。
  2. bashスクリプトから返された終了コード(呼び出し時exit)。
  3. 関数から返された終了コード(呼び出し時return)。これはとの間にある0と思います255

パート3では、シェル関数から戻ることを意味していますか?それはシェルに依存してもよいが、私はbashのマニュアルは言う「ことに注意して終了ステータスが間に入る0255と」「も、この範囲に限定されているシェル組み込みコマンドと化合物のコマンドからの終了ステータス。returnで、もちろん、シェルの組み込みを。
トビー・スペイト

関連(ほとんどの質問に対する回答があります):プロセスが終了したときのデフォルトの終了コード?
ステファンシャゼル

@TobySpeight、これはbashシェルの制限です。のような他のいくつかのシェルはzsh、forなどの符号付き32ビット値を返すことができexitます。サポートするタイプ(スカラーまたはリスト)のデータを好む、rcまたはes返すことができます。詳細については、リンク先のQ&Aをご覧ください。
ステファンシャゼル

回答:


74

_exit()/ exit_group()システムコールに渡される番号(終了ステータスとのあいまいさを避けるために終了コードと呼ばれることもあります。これは、プロセスが強制終了または正常終了したかどうかに応じて、終了コードまたはシグナル番号のエンコードと追加情報も参照します) )はtype intであるため、LinuxなどのUnix系システムでは、通常、-2147483648(-2 31)から2147483647(2 31 -1)までの値を持つ32ビット整数です。

すべてのシステム、親プロセスに(または子subreaperまたはしかし、init親が死亡した場合)は使用していますwait()waitpid()wait3()wait4()それを取得するためのシステムコールを、それの下位8ビットのみが利用可能(値が0〜2(255ある8 - 1))。

waitid()API(またはSIGCHLDのシグナルハンドラー)を使用する場合、ほとんどのシステムで(そしてPOSIXが標準の2016版_exit()仕様を参照)でより明確に要求されるように)、完全な番号が(si_status返される構造のフィールドで)利用可能です)。Linuxではまだそうではありませんが、waitid()APIで数値が8ビットに切り捨てられますが、将来的には変更される可能性があります。

一般に、多くのシェル$?終了ステータスの表現で128を超える値を使用して強制終了されているプロセスのシグナル番号をエンコードし、特別な場合は126と127をエンコードするため、値0(一般的に成功を意味する)のみを使用する必要があります条件。

exit()シェルの$?場合と同じことを意味するために、126〜255を使用したい場合があります(スクリプトの場合などret=$?; ...; exit "$ret")。通常、0-> 255以外の値を使用することは役に立ちません。通常は、waitid()切り捨てられないシステムで親がAPI を使用することがわかっていて、32ビット値の範囲が必要な場合にのみ、それを行います。あなたがしなければことに注意してくださいexit(2048)例えば、それは伝統的な使用の両親によって成功と見られるwait*()のAPIを。

詳細情報:

Q&Aが他の質問のほとんどに回答し、終了ステータスが何を意味するのかを明確にする必要があります。さらにいくつか追加します。

プロセスは、強制終了されるか_exit()/ exit_group()システムコールを呼び出さない限り終了できません。main()in から戻るCと、libcはそのシステムコールを戻り値で呼び出します。

ほとんどの言語には、exit()そのシステムコールをラップする関数があり、一般にシステムコールに渡される値がある場合はその値が使用されます。(これらは一般にexit()、stdioバッファーをフラッシュし、atexit()フックを実行するCの関数によって行われるクリーンアップのようなことを行うことに注意してください...)

少なくとも以下の場合です。

$ strace -e exit_group awk 'BEGIN{exit(1234)}'
exit_group(1234)                        = ?
$ strace -e exit_group mawk 'BEGIN{exit(1234)}'
exit_group(1234)                        = ?
$ strace -e exit_group busybox awk 'BEGIN{exit(1234)}'
exit_group(1234)                        = ?
$ echo | strace -e exit_group sed 'Q1234'
exit_group(1234)                        = ?
$ strace -e exit_group perl -e 'exit(1234)'
exit_group(1234)                        = ?
$ strace -e exit_group python -c 'exit(1234)'
exit_group(1234)                        = ?
$ strace -e exit_group expect -c 'exit 1234'
exit_group(1234)                        = ?
$ strace -e exit_group php -r 'exit(1234);'
exit_group(1234)                        = ?
$ strace -e exit_group zsh -c 'exit 1234'
exit_group(1234)

0-255以外の値を使用すると、不平を言うものが時々見られます。

$ echo 'm4exit(1234)' | strace -e exit_group m4
m4:stdin:1: exit status out of range: `1234'
exit_group(1)                           = ?

負の値を使用すると、いくつかのシェルが文句を言います。

$ strace -e exit_group dash -c 'exit -1234'
dash: 1: exit: Illegal number: -1234
exit_group(2)                           = ?
$ strace -e exit_group yash -c 'exit -- -1234'
exit: `-1234' is not a valid integer
exit_group(2)                           = ?

POSIXは、exit特別な組み込みに渡される値が0-> 255の外にある場合、動作を未定義のままにします。

一部のシェルでは、次のような予期しない動作が発生します。

  • bashmkshただし、pdkshベースとなるわけではありません)、値を8ビットに切り捨てます:

    $ strace -e exit_group bash -c 'exit 1234'
    exit_group(210)                         = ?
    

    そのため、これらのシェルで、0-255以外の値で終了したい場合は、次のようにする必要があります。

    exec zsh -c 'exit -- -12345'
    exec perl -e 'exit(-12345)'
    

    つまり、同じプロセスで別のコマンドを実行し、必要な値でシステムコールを呼び出すことができます。

  • 他のQ&Aで述べたように、ksh93257から256 + max_signal_numberまでの終了値に対して最も奇妙な動作があります。ここでは、を呼び出す代わりにexit_group()、対応するシグナルで自身を殺します¹。

    $ ksh -c 'exit "$((256 + $(kill -l STOP)))"'
    zsh: suspended (signal)  ksh -c 'exit "$((256 + $(kill -l STOP)))"'
    

    それ以外の場合は、bash/のような数値を切り捨てmkshます。


¹ただし、次のバージョンでは変更される可能性があります。の開発はksh93AT&T以外のコミュニティの取り組みとして引き継がれたため、その振る舞いはPOSIXによって何らかの形で奨励されていても、元に戻されています


2
si_statusLinux用の完全な終了コードの実装に関する議論があるかどうか知っていますか?
ルスラン

2
@Ruslan、以下austingroupbugs.net/view.php?id=594#c1318私が与えたリンクで(エリック・ブレイク(RedHatの)から)
ステファンChazelas

1
「int型なので、32ビット整数です」。Linuxはintが常に32ビットであることを本当に保証しますか?それらの小さなマイクロコントローラーのいくつかで実行しているときでさえ?それは本当に奇妙に思えます。POSIXは確かにそうではありません。
Voo

@Voo、これらの小さなマイクロコントローラーはLinuxを実行できません。Cはint少なくとも16ビットである必要がありますが、POSIXでは少なくとも32ビットである必要がありプログラミング環境ではuint32_tが必要です。Linuxがintが32ビット以外のプログラミング環境をサポートしているかどうかは知りませんが、私はこれに遭遇したことがありません。
ステファンシャゼル

1
POSIX準拠のOSでは、Bourne Shellの最新バージョンで32ビットの完全な終了コードを取得できます。schillix.sourceforge.net
man1

12

最小値は0であり、これが成功値と見なされます。他のすべては失敗です。最大値はとして255も知られてい-1ます。

これらのルールは、スクリプトと他の実行可能ファイル、およびシェル関数の両方に適用されます。

値が大きいほど、モジュロ256になります。


2
正確には、一部のBourneのようなシェル(ただし、bash最も一般的に使用されないシェル)では、exit組み込みに渡される終了コードはモジュロ256として扱われ、代わりにエラーが発生します。(たとえば、コモンexit -1は実際にexit 255はほとんどのシェルと同等の移植性のあるものではありません)。そしてexit(-1)、Cレベルで同等であるかどうかは、exit(255)事実上確実に機能しますが、実装定義の動作に依存します(ただし、これは実際に使用する現代のシステムでは問題になりません)。
mtraceur

私の知る限り、ksh93のみがexit(1)パラメーターを8ビットに制限しています。
44分

6

これはとても単純に見えますが、ああ、悲惨です。

C言語(および他のほとんどの言語に直接または間接的に続くもの)では、returnが戻り値と同じ引数でmain呼び出すことと同等であることが必要exitです。これは整数です(戻り値の型は非常に明確であるint)ので、原則的に範囲があることでしょうINT_MININT_MAX

ただし、POSIXではexit、文字通り「status&0xFF」であるかのように、渡された最下位の8ビットのみが待機中の親プロセスで利用できるようになっています。
そのため、実際には、終了コードは(まだ符号付きの)整数であり、その整数の最下位8ビットのみが設定されます。

したがって、最小値は-128、最大値は127です。ちょっと待ってください、それは真実ではありません。0〜255になります。

しかし、悲しいかな、もちろんそれはそれほど単純なことではありません。実際には、Linux(またはbash)のやり方は異なります。戻りコードの有効範囲は0〜255(つまり、符号なし)です。

混乱を避けるという点で安全を期すために、リターンコードが符号なしであると仮定し、返されたものを符号なしにキャストすることをお勧めしますwait。そうすれば、シェルに表示される内容と一致します。最上位ビット(最上位ビットを含む)はクリアされるため、技術的には署名されますが、実際の値は常に符号なし(符号ビットが設定されないため)であるため、「間違った」ものではありません。
また、終了コードとを比較する一般的なエラーを回避するのに役立ちます-1。これ、プログラムが終了した場合でも、何らかの奇妙な理由で表示されないよう-1です(理由を推測してください)。

この関数がたまたまある場合、関数から戻る最後のポイントについては、main上記を参照してください。それ以外の場合は、関数の戻り値の型に依存し、原則として何でもかまいません(を含むvoid)。


1989年の直前にwaitid()紹介されました。
シリー

@schily:どういう意味かわかりませんか?waitid()同じことをわずかに異なる方法で行います。これは、特定のIDまたは任意のスレッドを待ち、それは尖った-TOに結果を書き込みsiginfo_t構造体si_statusであるint(そう... 署名し、ちょうど同じ)。それでも、exit()最下位の8ビットのみを渡すので、...まったく同じことをボンネットの下で行います。
デイモン

exit()パラメータのwaitid()32ビットすべてをカーネルに渡し、終了コードから32ビットすべてを返します。たぶん、あなたは誰もバグの修正を気にしないLinuxでチェックしたでしょう。あなたは私を信じていない場合は、... POSIXの準拠のOS上でそれを確認
シリー

@schily:それが本当なら(そうだとは思いませんが、とにかく)、Linuxは壊れています。リンク・ツー・イン・解答POSIX仕様をお読みくださいexit:述べ、「説明」の下で、特定の2行目、「しかし(ステータス&0377である)だけ最下位8ビットが待っている親プロセスに利用できるものでなければなりません"。これが、準拠する実装の仕組みです。32ビットではなく、下位8ビットです。32ビットが渡されるための参照はありますか?
デイモン

Linuxが壊れていると言ったと思った。さらに悪いことに、Linuxカーネルの人々はバグの修正を拒否しています。あなたはPOSIX標準を読めば、あなたは、1995年バージョン(SUSv1)はcorrecly、もともと1989年にはSVr4によって導入された機能を説明し、標準の最近のバージョンは、(例えばSUSv7tc2)も、明示的にすることを説明していることがわかりますwaitid()し、siginfo_t構造体が渡さSIGCHLDハンドラ復帰exit()パラメータからのすべての32ビット。
シリー

2
  1. バイナリ実行可能ファイル(Cプログラムなど)から返された終了コード。
  2. bashスクリプトから返された終了コード(exitの呼び出し時)。

バイナリ実行可能ファイル、シェルスクリプト、またはその他のプロセスの終了コードは、0〜255の範囲です。より大きな値をに渡すことができexit()ますが、ステータスの下位8ビットのみがを通じて他のプロセスwait()

  1. 関数から返された終了コード(returnを呼び出したとき)。これは0〜255の間だと思います。

C関数は、ほぼすべての型を返すように宣言できます。戻り値の制限は、その型によって完全に決定されます。たとえば、関数を返す場合は-128〜127、関数を返す場合は0〜42 signed char億、関数を返すunsigned intまでの浮動小数点数などinfですdouble。そしてそれは、非数値型を数えるようにされていませんvoid *struct...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.