Linuxに標準の終了ステータスコードはありますか?


308

Linuxでは、終了ステータスが0の場合、プロセスは正しく完了したと見なされます。

セグメンテーション違反が11の終了ステータスになることがよくあるのを見てきましたが、これが単に私が作業する規則(そのように失敗したアプリ)が標準であるのか、それとも標準であるのかはわかりません。

Linuxのプロセスに標準の終了コードはありますか?


6
システム関数から返された「システムエラー番号」と呼ばれるものを探している場合は、errno
marinara

回答:


86

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'; エコー$?
42
$ sh -c 'kill -SEGV $$'; エコー$?
セグメンテーション違反
139
$ expr 139-128
11

これ以外のものがある場合は、プログラムにおそらく通常SIGSEGV呼び出さexitれるシグナルハンドラーがあるため、実際にはシグナルによって強制終了されることはありません。(プログラムは、SIGKILLおよび以外の信号を処理することを選択できますSIGSTOP。)


8
質問の表示方法を考えると、これは最も有用な(したがって受け入れられた)回答ではないようです。
David J.

332

パート1:高度なBashスクリプトガイド

いつものように、Advanced Bash Scripting Guideにすばらしい情報があります(これは別の回答でリンクされていましたが、非正規URLにリンクされていました)。

1: 一般エラーのキャッチオール
2:シェル組み込みの誤用(Bashのドキュメントによる)
126: 呼び出されたコマンドは実行できない
127: "コマンドが見つかりません"
128: 終了する引数が無効です
128 + n: 致命的なエラー信号 "n"
255:終了しますステータスが範囲外です(exitは0〜255の範囲の整数の引数のみを受け取ります)

パート2:sysexits.h

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 */

5
一部の種類のUNIXでは、2つのコマンドが終了ステータス2を使用して他のものを示すことに注意してください。たとえば、grepの多くの実装では、終了ステータス2を使用してエラーを示し、終了ステータス1を使用して、選択された行が見つからなかったことを示します。
NamshubWriter、

3
:BSD系にsysexits.hからの情報をまとめたmanページがありますman sysexits
georgebrock

6
@NamshubWriterが言ったこと。終了ステータス2は、Unixユーティリティでの誤ったコマンドラインの使用に対する普遍的な推奨事項であり、「UNIXのいくつかのフレーバー」だけでなく、一般的なものです。この回答に示すヘッダは、現在またはそれが1987年に書かれたとき、実際の慣習を反映していない
アレクシス

ABSは「素晴らしい」ものではありません。主題について読んでください。批判を見つけるのは難しいことではありません。
tripleee

しかし、実際の公式ソースコードはsysexits.hどこにありますか?manページ誰もが参照し続けるだけの散文です。たとえばEX_OK、他のコードのように規範的な方法でそれを参照しますが実際には定義しません。不足しているものは他にありますか?
Garret Wilson、

71

「1」 >>>一般的なエラーのキャッチオール

「2」 >>>シェル組み込みの誤用(Bashのドキュメントによる)

「126」 >>>呼び出されたコマンドは実行できません

「127」 >>> "コマンドが見つかりません"

「128」 >>>終了する引数が無効です

「128 + n」 >>>致命的なエラー信号 "n"

'130' >>>スクリプトはControl-Cで終了しました

'255' >>>範囲外の終了ステータス

これはbash用です。ただし、他のアプリケーションでは、異なる終了コードがあります。


1
どちらも同じ時間に答えたようです。天はあなたのリンクを参照して、それらを貼り付けるためにかなり速いなければならないであろう。
ネイサンFellman

6
「control-C yields 130」は、信号nの「128 + n」と一致することに注意してください。制御-Cは信号2であるSIGINT生成
ジョナサン・レフラー

3
これは、帰属のないABSから盗用されたようです。(ABSに誤った、または少なくとも誤解を招く情報が含まれているため、
わかり

4
Advanced Bash-Scripting Guideによると、これらは予約済みの終了コードです。つまり、これらの値は、ユーザー指定の終了パラメーターでは使用しないでください
ingyhere

53

古い回答では、終了ステータス2を正しく説明していません。彼らが主張することに反して、ステータス2は不適切に呼び出されたときにコマンドラインユーティリティが実際に返すものです。(はい、答えは9歳になる可能性があり、何百もの賛成投票があり、それでも間違いがあります。)

これは、正常終了、つまりシグナルによるものではない、長期にわたる終了ステータス規則です。

  • 終了ステータス0:成功
  • 終了ステータス1:プログラムで定義されている「失敗」
  • 終了ステータス2:コマンドラインの使用エラー

たとえば、diff比較するファイルが同一の場合は0を返し、異なる場合は1を返します。UNIXプログラムは、長年の慣例により、誤って呼び出された場合に終了ステータス2を返します(不明なオプション、引数の数など) 。たとえばdiff -Ngrep -Yまたはdiff a b cすべて$?が2に設定されます。これは、 Unixの初期の1970年代。

受け入れ答えは、コマンドがされたときに何が起こるかを説明し、信号により終了します。簡単に言えば、キャッチされていない信号による終了は、終了ステータスになります128+[<signal number>。例えば、SIGINTシグナル2)による終了は、終了ステータス130になります。

ノート

  1. いくつかの回答では、終了ステータス2を「bashビルトインの誤用」と定義しています。これは、bash(またはbashスクリプト)がステータス2で終了する場合にのみ適用されます。不正な使用エラーの特殊なケースと考えてください。

  2. sysexits.hに述べたように、最も人気のある答え、終了ステータスはEX_USAGE(「コマンドラインの使用方法の誤り」)64になるように定義される。しかし、これは現実を反映していない:私は知りません任意の一般的なUNIXユーティリティ間違った呼び出しの戻り64は、(例は歓迎していること)。ソースコードを注意深く読むと、それ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 oth­er exit statuses that random programs may 
     *    already return. 
    

    つまり、これらの定義は当時(1993年)の一般的な慣習を反映していないが、意図的にそれと互換性がなかった。もっと残念だ。


何べきことは、プログラムリターン SIGINT / Ctrlキーを押しながらCを引くことにより、ハンドルの終了を?まだ130?bash以外に別のシェルを使用することは重要ですか?
Gringo Suave

1
プログラムを実行しているシェルは無関係です。プロセスは理論的には、その親プロセスに応じて異なるステータスで終了することを選択できますが、これが発生するケースを聞いたことがありません。
アレクシス2018

1
プログラムがSIGINTをキャッチし、クリーンアップして終了すると、ステータスはプログラムにとって意味のあるものになります。たとえばmore、ターミナルモードをリセットし、ステータス0で終了します(試すことができます)。
アレクシス2018

1
この答えは、実際のケースよりもはるかに高い標準化を意味します。値2の意味の適切な標準化はなく、実際の練習は予想通り非常に混合されます。多くのツールが不適切な使用法に対して2を返すことは事実ですが、「不適切な使用法」の意味が明確に定義されておらず、他の多くのツールはこの規則に準拠していません。
tripleee

@tripleee「ツール」も明確に定義されていません!:-)確かに、誰でもコマンドラインプログラムを記述でき、何でも返すことができますが、Linuxよりも古くからある旧式の「Unixコマンドラインユーティリティ」、またはGNU coreutilsのコンテンツはかなり優れています。これについて一貫しています。そうでない場合は、この方法でステータス2を使用しないこのグループのツールをいくつか挙げてください。また、「不適切な使用法」はあなたの言葉です(そして私はそれが漠然とした言葉であることに同意します)。私は「コマンドライン使用エラー」を書きました。これはかなり具体的です:存在しないか互換性のないオプション、間違った数の非オプション引数など
alexis

25

成功を意味する0を除いて、標準の終了コードはありません。ゼロ以外でも、必ずしも失敗を意味するわけではありません。

stdlib.hはEXIT_FAILURE1とEXIT_SUCCESS0を定義しますが、それはそれだけです。

11はsegfaultのイベントでカーネルがプロセスを強制終了するために使用するシグナル番号であるため、segfaultの11は興味深いものです。カーネルまたはシェルのいずれかに、それを終了コードに変換するメカニズムが存在する可能性があります。


20

sysexits.hには、標準の終了コードのリストがあります。それは少なくとも1993年にさかのぼるようで、Postfixのようないくつかの大きなプロジェクトがそれを使用しているので、私はそれが進むべき道だと思います。

OpenBSDのmanページから:

style(9)によると、プログラムの終了時にエラー状態を示すために任意の値でexit(3)を呼び出すことはお勧めできません。代わりに、sysexitsからの事前定義された終了コードを使用する必要があります。これにより、プロセスの呼び出し元は、ソースコードを調べることなく、障害クラスに関する大まかな見積もりを取得できます。

8

最初の近似では、0は成功、0以外は失敗、1は一般的な失敗、1より大きいものは特定の失敗です。falseとtestの些細な例外は別として、どちらも成功すると1を与えるように設計されていますが、他にもいくつか例外があります。

より現実的には、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がパターンを見つけられなかった場合や、空のディレクトリをlsした場合よりも失敗ではありません。

したがって、残念ながら、非常に一般的に使用されている実行可能ファイルであっても、論理的な一連のルールを強制しないように見えるUNIXの能力。


私もdiffの動作を指摘しようとしていました。wgetにも詳細なエラー(たとえば、認証失敗の場合は6)がありますが、1 =一般的なエラー、2..n =特定のエラー
PypeBros

5

プログラムは16ビットの終了コードを返します。プログラムがシグナルで強制終了された場合、上位バイトには使用されたシグナルが含まれます。それ以外の場合、下位バイトはプログラマーによって返される終了ステータスです。

その終了コードはどのようにステータス変数$に割り当てられますか?その後、シェル次第です。Bashはステータスの下位7ビットを保持し、信号を示すために128 +(信号nr)を使用します。

プログラムの唯一の「標準」規則は、成功の場合は0、エラーの場合はゼロ以外です。使用される別の規則は、エラー時にerrnoを返すことです。


3

別の投稿者が述べたように、標準のUnix終了コードはsysexits.hによって定義されています。同じ終了コードがPocoなどのポータブルライブラリで使用されます-以下にそれらのリストを示します。

http://pocoproject.org/docs/Poco.Util.Application.html#16218

信号11は、戻りコードとは異なるSIGSEGV(セグメント違反)信号です。このシグナルは、不良ページアクセスに応答してカーネルによって生成され、プログラムを終了させます。シグナルのリストは、シグナルのmanページ(「man signal」を実行)にあります。


1

Linuxが0を返すと、成功を意味します。それ以外の場合は失敗を意味し、各プログラムには独自の終了コードがあるため、それらすべてをリストするのはかなり時間がかかります...!

11個のエラーコードについては、実際にはセグメンテーションフォールト番号です。これは、ほとんどの場合、プログラムが割り当てられていないメモリロケーションにアクセスしたことを意味します。


1
カーネルはこれを強制終了し、「出口値」を割り当てるため、常に11です。同様に、他のタイプのフォルトは常に同じ終了値を取得します。
Alex Gartrell
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.