終了ステータスが0の場合、プロセスはLinuxで正しく完了したと見なされます。
セグメンテーション違反が原因で終了ステータスが11になることがよくありますが、これが単に私が仕事をする慣習(そのように失敗したアプリがすべて内部的なもの)であるかどうかはわかりません。
Linuxのプロセスに標準の終了コードはありますか?
wait(2)
&co。 からの復帰時に、8ビットの戻りコードと8ビットの強制終了シグナルの数が単一の値に混合されます。
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
int main() {
int status;
pid_t child = fork();
if (child <= 0)
exit(42);
waitpid(child, &status, 0);
if (WIFEXITED(status))
printf("first child exited with %u\n", WEXITSTATUS(status));
/* prints: "first child exited with 42" */
child = fork();
if (child <= 0)
kill(getpid(), SIGSEGV);
waitpid(child, &status, 0);
if (WIFSIGNALED(status))
printf("second child died with %u\n", WTERMSIG(status));
/* prints: "second child died with 11" */
}
終了ステータスはどのように判断していますか?従来、シェルは8ビットの戻りコードのみを保管しますが、プロセスが異常終了した場合は高位ビットを設定します。
$ sh -c 'exit 42'; echo $? 42 $ sh -c 'kill -SEGV $$'; echo $? セグメンテーション障害 139 $ expr 139 - 128 11
あなたがこれ以外の何かを見ているならば、プログラムはおそらくSIGSEGV
シグナルハンドラをおそらく持っています、そしてそれは通常exit
を呼び出します、それでそれは実際にシグナルによって殺されていません。 (プログラムはSIGKILL
とSIGSTOP
以外のシグナルを処理することを選択できます。)
いつものように、 高度なBashスクリプトガイド は すばらしい情報 を持っています:(これは別の答えでリンクされていましたが、非正規URLにリンクされていました。)
1:一般的なエラーの検出
2:シェルビルトインの誤用(Bashのドキュメントによると)
126:呼び出されたコマンドは実行できません
127: "コマンドが見つかりません"
128:終了する引数が無効です
128 + n:致命的なエラー信号 "n"
255:終了ステータスが範囲外です(exitは0から255の範囲の整数引数のみを取ります)
ABSGはsysexits.h
を参照します。
Linuxの場合
$ find /usr -name sysexits.h
/usr/include/sysexits.h
$ cat /usr/include/sysexits.h
/*
* Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved.
(A whole bunch of text left out.)
#define EX_OK 0 /* successful termination */
#define EX__BASE 64 /* base value for error messages */
#define EX_USAGE 64 /* command line usage error */
#define EX_DATAERR 65 /* data format error */
#define EX_NOINPUT 66 /* cannot open input */
#define EX_NOUSER 67 /* addressee unknown */
#define EX_NOHOST 68 /* Host name unknown */
#define EX_UNAVAILABLE 69 /* service unavailable */
#define EX_SOFTWARE 70 /* internal software error */
#define EX_OSERR 71 /* system error (e.g., can't fork) */
#define EX_OSFILE 72 /* critical OS file missing */
#define EX_CANTCREAT 73 /* can't create (user) output file */
#define EX_IOERR 74 /* input/output error */
#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
#define EX_PROTOCOL 76 /* remote error in protocol */
#define EX_NOPERM 77 /* permission denied */
#define EX_CONFIG 78 /* configuration error */
#define EX__MAX 78 /* maximum listed value */
'1' >>>一般的なエラーを検出する
'2' >>>シェルビルトインの誤用(Bashのドキュメントによると)
'126' >>>呼び出されたコマンドは実行できません
'127' >>>「コマンドが見つかりません」
'128' >>>終了する引数が無効です
'128 + n' >>>致命的なエラー信号 "n"
'130' >>>スクリプトはControl-Cで終了しました
'255' >>>終了ステータスが範囲外です
これはbash用です。ただし、他のアプリケーションでは、さまざまな終了コードがあります。
古い回答では、終了ステータス2を正しく説明していません。彼らが主張していることに反して、ステータス2は、不適切に呼び出されたときにコマンドラインユーティリティが実際に返すものです。(はい、答えは9歳になることがあります数百の賛成票、そしてまだ間違っている。)
正常な終了、つまりシグナルによるものではない、実際の長期にわたる終了ステータスの規則を次に示します。
たとえば、diff
は、比較するファイルが同一の場合は0を返し、異なる場合は1を返します。長年の慣習により、unixプログラムは、誤って呼び出されたときにexit status 2を返します(不明なオプション、引数の数が間違っているなど)。たとえば、diff -N
、 grep -Y
またはdiff a b c
はすべて、$?
が2に設定されることになります。これは、1970年代のUnixの初期の頃から慣習となっています。
受け入れられた答え は、コマンドがシグナルによって終了した場合に何が起こるかを説明します。要するに、キャッチされなかったシグナルによる終了終了ステータス128+[<signal number>
。たとえば、SIGINT
( signal 2 )で終了すると、終了ステータス130になります。
いくつかの回答では、終了ステータス2を「bash組み込み関数の誤用」と定義しています。これは、bash(またはbashスクリプト)がステータス2で終了する場合にのみ適用されます。不正な使用エラーの特殊なケースと考えてください。
sysexits.h
では、 最も一般的な回答 で言及されていますが、終了ステータスEX_USAGE
(「コマンドライン使用エラー」)は64に定義されています。しかし、これは現実を反映していません。誤った呼び出しで64を返すany一般的なUnixユーティリティを認識しません(例は歓迎)。 ソースコード を注意深く読むと、sysexits.h
が真の使用法を反映したものではなく、意欲的なものであることがわかります。
* This include file attempts to categorize possible error * exit statuses for system programs, notably delivermail * and the Berkeley network. * Error numbers begin at EX__BASE [64] to reduce the possibility of * clashing with other exit statuses that random programs may * already return.
言い換えれば、これらの定義は当時(1993年)の一般的な慣行を反映していないが、意図的にそれと矛盾していた。残念です。
成功を意味する0を除いて、標準の終了コードはありません。ゼロ以外も必ずしも失敗を意味するわけではありません。
stdlib.hはEXIT_FAILURE
を1、EXIT_SUCCESS
を0と定義していますが、それだけです。
11はセグメンテーションフォールトの場合にカーネルがプロセスを終了させるために使用するシグナル番号であるため、セグメンテーションフォールトの11は興味深いものです。カーネルかシェルのどちらかに、それを終了コードに変換する何らかのメカニズムがある可能性があります。
sysexits.hは標準の終了コードのリストを持っています。それは少なくとも1993年までさかのぼり、Postfixのようないくつかの大きなプロジェクトがそれを使っているので、私はそれが進むべき道だと思う。
OpenBSDのmanページから:
スタイル(9)によると、プログラムを終了するときに失敗条件を示すために任意の値を指定してexit(3)を呼び出すことはお勧めできません。代わりに、sysexitsからの事前定義された終了コードを使用する必要があります。そのため、プロセスの呼び出し側は、ソースコードを調べずに失敗クラスに関する大まかな見積もりを取得できます。
最初の概算では、0は成功、0以外は失敗、1は一般的な失敗、そして1より大きいものは特定の失敗です。どちらも成功のために1を与えるように設計されているfalseとtestのささいな例外を除いて、私が見つけた他のいくつかの例外があります。
より現実的には、0は成功または失敗の可能性を、1は一般失敗または成功の可能性を、2は1と0の両方が成功に使用されている場合は一般失敗を意味します。
Diffコマンドは、比較されたファイルが同一の場合は0、それらが異なる場合は1、バイナリが異なる場合は2を返します。 2は失敗も意味します。引数の指定に失敗しない限り、lessコマンドは失敗のために1を与えます。その場合、失敗しても0を終了します。
失敗が許可の拒否、存在しないファイル、またはディレクトリの読み取りの試みの結果でない限り、moreコマンドおよびspellコマンドは失敗のために1を与えます。いずれの場合も、失敗しても0で終了します。
その後、exprコマンドは、出力が空の文字列またはゼロでない限り、1に成功します。その場合、0が成功します。 2と3は失敗です。
その後、成功または失敗があいまいな場合があります。 grepがパターンを見つけられなかった場合、それは1を終了しますが、本物の失敗のために2を終了します(許可が拒否されたように)。チケットが見つからなかった場合もKlistは1で終了しますが、grepがパターンを見つけられなかった場合や空のディレクトリを探した場合よりも、これは実際にはそれほど失敗にはなりません。
したがって、残念なことに、非常に一般的に使用されている実行可能ファイルであっても、unixの力によって論理的な一連の規則が強制されることはないようです。
プログラムは16ビットの終了コードを返します。プログラムがシグナルで強制終了された場合、上位バイトには使用されたシグナルが含まれます。それ以外の場合、下位バイトはプログラマーによって返された終了ステータスです。
その終了コードは、ステータス変数$にどのように割り当てられますか?それからシェル次第です。 bashはステータスの下位7ビットを保持してから、シグナルを示すために128 +(シグナルnr)を使用します。
プログラムのための唯一の「標準の」慣習は、成功の場合は0、エラーの場合はゼロ以外の値です。使用されるもう1つの規則は、エラー時にerrnoを返すことです。
別の投稿者が述べたように、標準のUnix終了コードはsysexits.hによって定義されています。同じ終了コードがPocoのような移植性のあるライブラリでも使われています - それらのリストは以下のとおりです。
http://pocoproject.org/docs/Poco.Util.Application.html#16218
シグナル11はSIGSEGV(セグメント違反)シグナルであり、戻りコードとは異なります。このシグナルは、不正なページアクセスに応答してカーネルによって生成され、プログラムが終了します。シグナルのリストはsignalのmanページにあります(run "man signal")。
Linuxが0を返した場合、それは成功を意味します。それ以外のことは失敗を意味します、それぞれのプログラムはそれ自身の終了コードを持っています、それでそれらすべてをリストするのはかなり長いでしょう…!
11のエラーコードについて、それは確かにセグメンテーションフォルト番号、プログラムが割り当てられていないメモリ位置にアクセスしたことを主に意味します。