GNU/Linux >> Linux の 問題 >  >> Linux

プロセスが終了したときのデフォルトの終了コード?

SIGINTのような処理可能なシグナルでプロセスが強制終了された場合 またはSIGTERM ただし、シグナルは処理されません。プロセスの終了コードは何になりますか?

SIGKILLのような処理できない信号についてはどうでしょうか ?

私の知る限り、SIGINTでプロセスを強制終了します 終了コード130になる可能性があります 、しかし、それはカーネルまたはシェルの実装によって異なりますか?

$ cat myScript
#!/bin/bash
sleep 5
$ ./myScript
<ctrl-c here>
$ echo $?
130

他の信号をどのようにテストするかわかりません…

$ ./myScript &
$ killall myScript
$ echo $?
0  # duh, that's the exit code of killall
$ killall -9 myScript
$ echo $?
0  # same problem

承認された回答:

プロセスは_exit()を呼び出すことができます システムコール(Linuxの場合、exit_group()も参照してください。 )親に終了コードを報告する整数引数を使用します。整数ですが、親が使用できるのは最下位8ビットのみです(waitid()を使用する場合は例外です。 または、親のSIGCHLDのハンドラーを使用して、そのコードを取得します。ただし、Linuxではありません。

親は通常、wait()を実行します またはwaitpid() ステータスを取得するには 整数としての子の(waitid() セマンティクスが多少異なる場合も使用できます)。

LinuxおよびほとんどのUnicesでは、プロセスが正常に終了した場合、そのステータスのビット8〜15 numberには、exit()に渡された終了コードが含まれます 。そうでない場合は、最下位7ビット(0〜6)に信号番号が含まれ、コアがダンプされた場合はビット7が設定されます。

perl$? たとえば、waitpid()で設定された番号が含まれています :

$ perl -e 'system q(kill $$); printf "%04xn", $?'
000f # killed by signal 15
$ perl -e 'system q(kill -ILL $$); printf "%04xn", $?'
0084 # killed by signal 4 and core dumped
$ perl -e 'system q(exit $((0xabc))); printf "%04xn", $?'
bc00 # terminated normally, 0xbc the lowest 8 bits of the status

ボーンのようなシェルは、最後の実行コマンドの終了ステータスを独自の$?にします。 変数。ただし、waitpid()によって返される番号は直接含まれていません。 、しかしそれに対する変換であり、シェル間で異なります。

すべてのシェルに共通しているのは、その$? 終了コードの下位8ビット(exit()に渡される番号)が含まれます )プロセスが正常に終了した場合。

異なるのは、プロセスがシグナルによって終了する場合です。いずれの場合も、POSIXで必要とされる数は、128より大きくなります。POSIXは値が何であるかを指定しません。しかし実際には、私が知っているすべてのボーンのようなシェルでは、$?の下位7ビットです。 信号番号が含まれます。ただし、n は信号番号です

  • ash、zsh、pdksh、bash、Bourneシェル、$? 128 + nです 。つまり、これらのシェルでは、$?を取得した場合です。 129の 、プロセスがexit(129)で終了したためかどうかはわかりません またはそれが信号1によって殺されたかどうか (HUP ほとんどのシステムで)。ただし、シェルが終了すると、デフォルトでは最後に終了したコマンドの終了ステータスが返されるというのが理論的根拠です。 $?を確認してください が255を超えることはありません。これにより、一貫した終了ステータスを得ることができます。

    $ bash -c 'sh -c "kill $$"; printf "%xn" "$?"'
    bash: line 1: 16720 Terminated              sh -c "kill $$"
    8f # 128 + 15
    $ bash -c 'sh -c "kill $$"; exit'; printf '%xn' "$?"
    bash: line 1: 16726 Terminated              sh -c "kill $$"
    8f # here that 0x8f is from a exit(143) done by bash. Though it's
       # not from a killed process, that does tell us that probably
       # something was killed by a SIGTERM
    
  • ksh93$? 256 + nです 。つまり、$?の値から 強制終了されたプロセスと強制終了されていないプロセスを区別できます。 kshの新しいバージョン 、終了時に、$?の場合 が255より大きい場合、同じ終了ステータスを親に報告できるようにするために、同じシグナルで自身を強制終了します。それは良い考えのように聞こえますが、それはkshを意味します プロセスがコア生成信号によって強制終了された場合、追加のコアダンプが生成されます(他のコアダンプが上書きされる可能性があります):

    $ ksh -c 'sh -c "kill $$"; printf "%xn" "$?"'
    ksh: 16828: Terminated
    10f # 256 + 15
    $ ksh -c 'sh -c "kill -ILL $$"; exit'; printf '%xn' "$?"
    ksh: 16816: Illegal instruction(coredump)
    Illegal instruction(coredump)
    104 # 256 + 15, ksh did indeed kill itself so as to report the same
        # exit status as sh. Older versions of `ksh93` would have returned
        # 4 instead.
    

    バグがあるとさえ言えるのは、ksh93 $?であっても、自殺します return 257から取得 関数によって実行されます:

    $ ksh -c 'f() { return "$1"; }; f 257; exit'
    zsh: hangup     ksh -c 'f() { return "$1"; }; f 257; exit'
    # ksh kills itself with a SIGHUP so as to report a 257 exit status
    # to its parent
    
  • yashyash 妥協案を提供します。 256 + 128 + nを返します 。つまり、強制終了されたプロセスと適切に終了したプロセスを区別することもできます。終了すると、128 + nが報告されます 自殺する必要はなく、それがもたらす可能性のある副作用もありません。

    $ yash -c 'sh -c "kill $$"; printf "%xn" "$?"'
    18f # 256 + 128 + 15
    $ yash -c 'sh -c "kill $$"; exit'; printf '%xn' "$?"
    8f  # that's from a exit(143), yash was not killed
    

$?の値からシグナルを取得するには 、移植可能な方法は、kill -lを使用することです :

$ /bin/kill 0
Terminated
$ kill -l "$?"
TERM

(移植性のために、シグナル番号は使用しないでください。シグナル名のみを使用してください)

関連:バイトレベルとファイルレベルのバックアップ?

ボーン以外の面で:

  • csh / tcsh およびfish ステータスが$statusにあることを除いて、Bourneシェルと同じです。 $?の代わりに (zshに注意してください $statusも設定します cshとの互換性のため ($?に加えて ))。
  • rc :終了ステータスは$statusにあります 同様ですが、シグナルによって強制終了されると、その変数にはシグナルの名前が含まれます(sigtermなど)。 またはsigill+core コアが生成された場合)数値の代わりに、これはそのシェルの優れた設計のさらに別の証拠です。
  • es 。終了ステータスは変数ではありません。気になる場合は、次のようにコマンドを実行します。

    status = <={cmd}
    

    数値またはsigtermを返します またはsigsegv+core rcのように 。

完全を期すために、zshについて言及する必要があります。 の$pipestatus およびbash$PIPESTATUS 最後のパイプラインのコンポーネントの終了ステータスを含む配列。

また、完全を期すために、シェル関数とソースファイルに関しては、デフォルトでは、関数は最後のコマンド実行の終了ステータスで戻りますが、returnで明示的に戻りステータスを設定することもできます。 ビルトイン。ここにいくつかの違いがあります:

  • bash およびmksh (R41以降、regression ^ Wchangeは明らかに意図的に導入されています)数値(正または負)を8ビットに切り捨てます。たとえば、return 1234 $?を設定します 210へ 、return -- -1 $?を設定します 〜255。
  • zsh およびpdksh (およびmksh以外の派生物 )任意の符号付き32ビット10進整数(-2から2-1)を許可します(そして数値を32ビットに切り捨てます)。
  • ash およびyash 0から2-1までの任意の正の整数を許可し、それ以外の任意の数に対してエラーを返します。
  • ksh93 return 0の場合 return 320 $?を設定します そのままですが、それ以外の場合は、8ビットに切り捨てます。すでに述べたように、256〜320の数値を返すと、kshが発生する可能性があることに注意してください。 終了時に自殺する。
  • rc およびes リストも含めて何でも返すことができます。
関連:arduino – gcodeはインタプリタからの応答コードを必要としますか?

また、一部のシェルは$?の特別な値も使用することに注意してください / $status 127など、プロセスの終了ステータスではないエラー状態を報告する場合 または126 コマンドが見つかりません または実行可能ではありません (またはソースファイルの構文エラー)…


Linux
  1. Bashコマンドラインの終了コードがわかりやすく説明されています

  2. 親プロセスが終了したときの新しい親プロセス?

  3. assert() が失敗した場合、プログラムの終了コードは何ですか?

  1. exit() がプロセスの終了に失敗することはありますか?

  2. セグメンテーション違反を起こしたプロセスが返すエラー コードは何ですか?

  3. 期待されるシェルスクリプトで生成されたプロセスの終了コードを取得するには?

  1. スレッドが分岐するとどうなりますか?

  2. kill を使用してプロセスを停止するときに、特定の終了コードを強制することは可能ですか?

  3. プロセスを kill -9 してはいけないのはいつですか?