失敗した猫は1を返し、他の失敗した猫は2を返すのはなぜですか?

失敗した猫は1を返し、他の失敗した猫は2を返すのはなぜですか?

考慮事項:(Linux / BASHを使用して、UNIXが正しいかどうかわからない)

存在しないファイルについて議論すると、2つのエラーが予想されました。

grep "i am here" real-file

# Returns: 0 (via: echo $?)

grep "i am not here" real-file

# Returns: 1

grep "i am not here" not-a-file

# Returns: 2 (No such file or directory)

ls real-files

# Returns: 0

ls not-files

# Returns: 2 (No such file or directory)

…みんな言葉になるけど…

cat real-files

# Returns: 0

cat not-files

# Returns: 1 (No such file or directory)

...「該当するファイルやディレクトリはありません」は終了ステータス2のSTDERRではないはずですか?

状態2にはファイルがあり、grepファイルlsはありませんが、cat同じエラーメッセージで1を返します。

私はgrep3つの可能な結果(上記のそれぞれ)があることを知っていますが、2つのlsことがあると思いますcat。したがって、2つの考えられる結果は原因にはなりませcatls

BASHコードに問題がありますか? LinusとRichardに電話する必要がありますか?これが正しい場合は、その理由を理解するのに役立ちます。


回答を受け入れた後、元の質問を拡張する回答が必要です。これはUNIXではなくLinux/BASHだからです。正しい:UNIX(Macなど)は同じことをしますか、それとも同じことをしますか?

答え1

下から上にいくつかの部分をカバーし、重要でない部分を最初に削除してみましょう。

BASHコードに問題がありますか?

いいえ、一部のシェル構成で指摘したように、cat完全にスタンドアロンのバイナリアプリケーションです。bashスティーブン・チャジェラスcat組み込み可能ですが、アプリケーションの戻り状態は、アプリケーションがシェル関連かどうかとは完全に独立しています。

LinusとRichardに電話する必要がありますか?これが正しい場合は、その理由を理解するのに役立ちます。

いいえ、それは問題ではありません。 LinusとRichardはここでは何もしません。まあ、訂正します。いつか彼らはerrnoexit()とerrnoが絶対に関連するべきであると言い、何らかの奇妙な理由で私たちは彼らのすべての技術的決定に従うべきだと言わない限り。


両方のアプリケーションが異なる終了状態を返すことはまったく問題ではありません。POSIX 仕様には、「ゼロ以外の終了状態がこれを意味する」という明示的な制限や割り当てはありません。

シャットダウンシステムコールのPOSIXドキュメント状態:

ステータス値は0、EXIT_SUCCESS、EXIT_FAILURE、またはその他の値ですが、待機している親プロセスには最下位8ビット(つまりステータスと0377)のみを使用できます。

これは状態0のみが指定された意味を持ち、これは次のようにEXIT_SUCCESSに割り当てられることを意味します。標準ライブラリファイルメガネ。しかし、これはPOSIX仕様です。 Linux仕様はどのように比較されますか?まあ、ほぼ同じです:Linux出口(3)マニュアルには可能な値も指定されていません。

また、「~しなければならない」ではなく「~であるかもしれない」と書かれていることに注意してください。アプリケーションが特定の値で終了する必要はありません。、エラーが発生しても。アプリケーションでエラーが発生または失敗する可能性がありますが、まだゼロで終了します。

ただし、POSIX仕様はすべてのポータブルアプリケーション用EXIT STATUS部分が実際に指定されました。各アプリケーションによって異なります。繰り返しますが、成功の場合はゼロ以外のパターンはなく、他の場合はゼロ以外のパターンはありません。例えば、POSIX猫仕様必要:

The following exit values shall be returned:

0    All input files were output successfully.

>0   An error occurred.

~のためgrep私たちは:

The following exit values shall be returned:

 0    One or more lines were selected.
 1    No lines were selected.
>1    An error occurred.

Linux環境では猫(1)これらの状態値は明示的に明示されていませんが、GNUドキュメントは正規表現(1)マニュアルには終了コード2を使用することが言及されていますが、POSIX実装には0より大きいエラー条件のみが必要であることを認めています。 「と呼びかけます。


exit()場合によっては、状態値が次のと仮定することは言及する価値があります。エラー番号値。これまでPOSIXでこれを要求しているという文書や参考資料が見つかりませんでした。実際には、その逆は事実です。 POSIXに注目してください出口規範とLinux出口(3) マニュアルページ欲しくない終了状態が何らかの方法で errno と一致する必要があることを明示的に示します。したがって、戻り値2とGNUのgrepENOENTエラー値2との一致は純粋に偶然です。

実際に考えてみるとエラー番号 特定の整数値を割り当てる必要さえなく、実装によって異なります。したがって、 ENOENT を整数 2 として扱う Unix と同様の実装がある可能性が高いです。しかし、終了状態とerrnoは異なるため、これはまったく関係ありません。

要約すると:

実際にcat返される終了コードはgrep異なり、そのアプリケーションの仕様と一致し、適切です。終了コードの意味は固定されておらず、個々のアプリケーションによって異なります(catまたはPOSIXアプリケーション以外grepの場合は移植性のために従う必要があります)。

見積もりGNUオペレーティングシステムのドキュメント: 「最も一般的なルールは、0は成功を意味し、1は失敗を意味します.比較を実行するプログラムは別のルールを使用します.次のような場合、プログラムは既存の規則に従う必要があります。

答え2

牛に似た一種の栄養coreutils ドキュメントcat

終了状態 0 は成功を示し、ゼロ以外の値は失敗を示します。

... 0以外の終了状態は失敗のみを意味します。

次のマニュアルページgrep

通常、終了状態は、行が選択されている場合は0、行が選択されていない場合は1、エラーが発生した場合は2です。ただし、-qまたはを使用して行を選択すると、--quietエラー--silentが発生しても終了ステータスは0です。

そして次のマニュアルページls

終了ステータス:
0は正常、
1はマイナーな問題(サブディレクトリにアクセスできないなど)、
2は深刻な問題(コマンドライン引数にアクセスできません)です。

結果は文書と一致します。

答え3

プログラムの終了状態は、これらの規則に加えていくつかの一般的な規則に従う必要があります。これらのルールは、プログラムの終了を引き起こす低レベルのエラーとは何の関係もありません。終了時に特定のエラーコードを表示し(ファイルが存在しないため終了することを決定)、ファイルへのアクセスを拒否して終了することを決定した場合は、他のエラーコードを表示するプログラムを作成できます。パスのディレクトリコンポーネントがディレクトリではないことが判明した場合、他のエラーコードが発生します。しかし、これは非常に異例であり、整理するのが難しいです。

プログラムの終了状態は整数値です。存在するPOSIXシステム、この値の型はint通常、値の範囲は-2 31から2 31 +1です。ただし、この範囲のほとんどはさまざまな理由で実際には使用できません。とりわけ、歴史的な理由でプログラムが子プロセスの終了状態を観察できるようにするほとんどのインタフェースは、終了状態の下位8ビット(0から255の値)のみを返します。これにはシステム機能が含まれます。waitそしてwaitpidしかもシェルの終了状態².したがって、ほぼすべての意図と目的に応じて、終了状態は8ビット値です。

ゼロ値は成功とみなされ、他のすべての値は失敗と見なされます。これはシェルの場合です。ブール演算子ifそしてwhileビルドtrue / false概念に関連する他のすべての項目は、終了状態0をtrueとして処理し、他のすべての状態をfalseとして処理します。これも同じです。makeゼロ以外の終了状態のため、エラーメッセージとエラー状態とともにビルドが停止します。これが慣例であるか疑問を提起することができます(技術的には、プログラム作成者は希望の状態を返すことができ、「成功」と「失敗」は正式に定義されていないからです)。しかし、実際には状態から始まります。 0の場合、成功したと見なされ、別の状態(1-255)で終了したプログラムは失敗したと見なされます。

エンクロージャの特に範囲を制限するもう1つの特徴は次のとおりです。シェルの終了状態$?追加情報のエンコード(観察を通して):

  • 126 は、コマンド名が既存のファイルであるため実行できないことを意味します。
  • 127 はコマンド名が見つからないことを意味します。
  • 128+窒素伝統的に(そして今日でもまだほとんどのシェルでは)、コマンドは信号で終了するように指示されました。窒素。一部のシェルは常に128を超えるさまざまな範囲を使用します。

したがって、実際には、プログラムは125より大きい終了状態を効果的に使用できません。これにより、1-125の値がさまざまなエラーを示すことができます。

より大きな値が「より悪い」失敗と見なされるという普遍的な慣習とは距離が離れていますが、普及しています。特に、検索コマンドの場合、grep1は「見つかりません」を意味し、2以上は検索を妨げるいくつかのエラーを意味します(たとえば、ファイルを見つけたが検索文字列を含まないとは異なり、ファイルが見つかりません) 。同様に、次の比較コマンドもあります。cmpそしてdiff終了ステータス0は「同じファイル」を意味し、1は「他のファイル」を意味し、2以上は「エラーのため比較を完了できません」を意味します。

一部のプログラムは、さまざまなエラーに対して異なるエラーコードを定義します。メールを送信その他のメール関連プログラム(で定義された値)sysexits.h)、同期カール得る

エラーコードの最も一般的なルールは、成功の場合は0、失敗の場合は1です。 C および C++ プログラミング言語の定義EXIT_FAILURE終了ステータスコードで、特定の値を選択する特別な理由がない場合は失敗を報告するために使用され、EXIT_FAILUREほとんどのシステムでは1です。

「該当するファイルまたはディレクトリなし」、「権限が拒否されました」、「ディレクトリではありません」などのエラーには、後に数字コードがあります。errno何が間違っているかを示すためにシステム機能によって返される値。 Errno値は通常プログラムの終了状態として使用されません。特定のプログラムの意味ではなく、何が間違っているかに関する詳細をエンコードします。例えば得るシャットダウン状態は、「オプションの解析エラー」(通常はデフォルトのシステムエラーなし)、「ローカル入力/出力エラー」(基本システムエラーに関係ありません)、「ネットワークエラー」(通常はローカルシステムエラーと同じ)を区別します。 wgetが破損したパイプ(パイプに書き込んだり、ネットワークソケットで接続を閉じたりするなど)によって失敗したかどうかを知るよりも、ネットワークエラーまたはローカルファイルエラーが原因でwgetが失敗したかどうかを知る方が便利です。設定ファイルが読み取れないか、ローカルポリシーネットワークアクセスが拒否されましたか?

戻り状態が errno 値に従うのはあまり一般的ではありません。 Perl方式のた​​め、特にPerlスクリプトでこれが起こります。die機能が機能します。しかし、これは悪い考えです。上記のように、errno値が情報の最も有用な部分ではないだけでなく、主にerrno値が1〜125の範囲にある理由がないためです。幸いなことに、私は1から255の範囲外のerrno値を持つシステムを知らないので、少なくともexit(errno)(またはPerlの場合die)256の倍数で終了しません。これは上から見たように成功。しかし、Linuxで、たとえば126まで(「RF-killのために操作を実行できません」)exit(errno)で終了するプログラムは、SIGILL(不正コマンド)で終了するプログラムと区別できません。errno == ERFKILL

^ waitidint全体的な価値へのアクセスを許可しますinfop->si_status
²または他の方法で$?。たとえば、exit256で終わるプログラムの場合、exit(256)シェルコマンドはif exit256; then echo "exited with 0"; fi"exited with 0"を印刷します。

答え4

システムによっては、catこれは組み込みシェルでも別のバイナリでもかまいません。それが何であるかを見るために実行することができます

$ command -V cat

また、catPOSIXを引用してGNUの動作は実際には正確です。猫(1):

終了ステータス

次の終了値を返す必要があります。

0
すべての入力ファイルが正常にエクスポートされました。

> 0
エラーが発生しました。

errnoと終了状態の関係はただ偶然です。 errnoは終了コードの下位8ビット内にある必要がないためです(POSIXではこれらのコードを渡す必要があります)。

ただし、POSIX '01準拠のSunOS 5.10は2を返します(XPG3とPOSIX '01の間に標準がないため、ツールの動作が変わっているようです)。

$ PATH=`getconf -v POSIX.1-2001 PATH`
$ export PATH
$ command -v cat
/usr/bin/cat
$ cat nosuchfile
cat: cannot open nosuchfile
$ echo $?
2

ENOENTこれはSolarisでも発生します。

$ grep ENOENT /usr/include/sys/errno.h
#define ENOENT  2       /* No such file or directory            */

しかし、マンページには>2だけが文書化されています。

関連情報