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
-
yash
。yash
妥協案を提供します。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
リストも含めて何でも返すことができます。
また、一部のシェルは$?
の特別な値も使用することに注意してください / $status
127
など、プロセスの終了ステータスではないエラー状態を報告する場合 または126
コマンドが見つかりません または実行可能ではありません (またはソースファイルの構文エラー)…