web-dev-qa-db-ja.com

stdin、stdout、stderrについて混乱していますか?

私は、これらの3つのファイルの目的にかなり混乱しています。私の理解が正しければ、stdinはプログラムがプロセス内のタスクを実行するリクエストに書き込むファイルであり、stdoutはカーネルが出力を書き込むファイルであり、stderrは情報へのアクセスを要求するプロセスです。すべての例外が入力されるファイル。これらのファイルを開いてこれらが実際に発生するかどうかを確認したところ、そのように思われるものは何もありませんでした!

私が知りたいのは、これらのファイルの目的は何なのか、非常に小さな技術用語では絶対に馬鹿げた答えです!

178
Shouvik

標準入力-これは、プロセスがユーザーから情報を取得するために読み取るファイルハンドルです。

標準出力-プロセスは、このファイルハンドルに通常の情報を書き込みます。

標準エラー-プロセスはこのファイルハンドルにエラー情報を書き込みます。

それは私がそれを作ることができるのと同じくらいばかげている:-)

もちろん、それはほとんど慣例によるものです。必要に応じて、標準出力にエラー情報を書き込むことを妨げるものは何もありません。 3つのファイルハンドルを完全に閉じて、I/O用に独自のファイルを開くこともできます。

プロセスが開始されると、これらのハンドルは既に開いているはずであり、それらからの読み取りおよび/または書き込みのみが可能です。

デフォルトでは、おそらく端末デバイス(/dev/ttyなど)に接続されていますが、シェルを使用すると、プロセスを開始する前に、これらのハンドルと特定のファイルやデバイス(または他のプロセスへのパイプライン)の間の接続を設定できます可能な操作のかなり賢いです)。

例:

my_prog <inputfile 2>errorfile | grep XYZ

これは:

  • my_progのプロセスを作成します。
  • inputfileを標準入力として開きます(ファイルハンドル0)。
  • errorfileを標準エラーとして開きます(ファイルハンドル2)。
  • grepのプロセスを作成another
  • my_progの標準出力をgrepの標準入力に添付します。

あなたのコメントを再:

これらのファイルを/ devフォルダーで開くと、実行中のプロセスの出力が表示されないのはなぜですか?

通常のファイルではないためです。 UNIXはeverythingをファイルシステム内のファイルとしてどこかに提示しますが、最低レベルではそうではありません。 /dev階層のほとんどのファイルは、文字デバイスまたはブロックデバイスのいずれかであり、事実上デバイスドライバーです。サイズはありませんが、メジャーとマイナーのデバイス番号があります。

それらを開くと、物理ファイルではなくデバイスドライバーに接続されます。また、デバイスドライバーは、個別のプロセスを個別に処理する必要があることを認識できるほどスマートです。

Linuxの/procファイルシステムにも同じことが言えます。これらは実際のファイルではなく、カーネル情報への厳密に制御されたゲートウェイです。

198
paxdiablo

stdinstdout、およびstderrはファイルではなく「I/Oストリーム」と言う方が正しいでしょう。お気づきのとおり、これらのエンティティはファイルシステムに存在しません。しかし、I/Oに関する限り、Unixの哲学は「すべてがファイル」です。実際には、それは本当に同じライブラリー関数とインターフェース(printfscanfreadwriteselectなど)を使用できることを意味しますI/Oストリームがキーボード、ディスクファイル、ソケット、パイプ、またはその他のI/O抽象化に接続されているかどうかを心配することなく。

ほとんどのプログラムでは、入力の読み取り、出力の書き込み、エラーのログ記録が必要です。そのため、プログラミングの都合上、stdinstdout、およびstderrが事前に定義されています。これは単なる慣習であり、オペレーティングシステムによって強制されるものではありません。

45
Jim Lewis

上記の答えを補完するものとして、リダイレクトに関する要約を示します。 Redirections cheatsheet

編集:このグラフィックは完全に正しいわけではありませんが、理由はわかりません...

グラフィックでは、2>&1には&>と同じ効果があると書かれています

ls Documents ABC > dirlist 2>&1
#does not give the same output as 
ls Documents ABC > dirlist &>
33
Leopold Gault

あなたの理解は完全に逆行していると思います。 :)

「標準入力」、「標準出力」、および「標準エラー」は、カーネルの観点ではなくプログラムの観点から考えてください。

プログラムが出力を印刷する必要がある場合、通常は「標準出力」に印刷します。通常、プログラムはprintfを使用して出力を標準出力に出力しますが、これは標準出力にのみ出力されます。

プログラムがエラー情報(必ずしも例外ではなく、はるかに高いレベルで課せられたプログラミング言語の構成である)を印刷する必要がある場合、通常は「標準エラー」に印刷されます。通常、fprintfを使用して、印刷時に使用するファイルストリームを受け入れます。ファイルストリームは、書き込み用に開かれた任意のファイル(標準出力、標準エラー、またはfopenまたはfdopenで開かれた他のファイル)です。

「標準入力」は、ファイルがfreadまたはfgets、またはgetcharを使用して入力を読み取る必要がある場合に使用されます。

これらのファイルはいずれも、次のようにシェルから簡単にリダイレクトにできます。

cat /etc/passwd > /tmp/out     # redirect cat's standard out to /tmp/foo
cat /nonexistant 2> /tmp/err   # redirect cat's standard error to /tmp/error
cat < /etc/passwd              # redirect cat's standard input to /etc/passwd

または、エンチラーダ全体:

cat < /etc/passwd > /tmp/out 2> /tmp/err

2つの重要な注意事項があります:最初に、「標準入力」、「標準出力」、および「標準エラー」は単なる慣習です。これらは非常に強力な規則ですが、次のようなプログラムを実行できることは非常に素晴らしいことです。grep echo /etc/services | awk '{print $2;}' | sortと各プログラムの標準出力をパイプラインの次のプログラム。

次に、ファイルストリーム(FILE *オブジェクト)を操作するための標準ISO C関数を指定しました-カーネルレベルでは、すべてのファイル記述子(intはファイルテーブルへの参照)であり、readwriteなどのはるかに低いレベルの操作です、ISO C関数の幸せなバッファリングを行いません。私はそれをシンプルに保ち、より簡単な機能を使用することを考えましたが、私はあなたが代替案を知っておくべきだと同じことを考えました。 :)

22
sarnold

標準

コンソールからの入力を読み取ります(キーボード入力など)。 scanfでCで使用

scanf(<formatstring>,<pointer to storage> ...);

標準

コンソールへの出力を生成します。 Cでprintfとともに使用

printf(<string>, <values to print> ...);

stderr

コンソールに「エラー」出力を生成します。 Cでfprintfとともに使用

fprintf(stderr, <string>, <values to print> ...);

リダイレクション

Stdinのソースはリダイレクトできます。たとえば、キーボード入力からではなく、ファイル(echo < file.txt)または別のプログラム(ps | grep <userid>)から取得できます。

Stdout、stderrの宛先もリダイレクトできます。たとえば、stdoutはファイルls . > ls-output.txtにリダイレクトできます。この場合、出力はファイルls-output.txtに書き込まれます。 Stderrはリダイレクト可能 with 2>

7
mikek3332002

stderrをエラーメッセージにのみ使用すべきだと言う人は誤解を招くと思います。

また、コマンドを実行しているユーザー向けであり、データの潜在的なダウンストリームコンシューマ向けではない情報メッセージにも使用する必要があります(つまり、複数のコマンドをチェーンするシェルパイプを実行する場合、消費者を混乱させるため、stdoutに42424 "と表示されますが、ユーザーにそれらを表示したい場合があります。

歴史的根拠については this をご覧ください:

「すべてのプログラムは診断を標準出力に配置しました。これにより、出力がファイルにリダイレクトされると常に問題が発生しましたが、出力が疑わないプロセスに送信されると耐えられなくなりました。標準出力モデルでは、人々はこの状況をv6まで容認していましたが、その後すぐに、デニスリッチーが標準エラーファイルを導入してゴーディアン結び目を切りました。自分自身を識別するために。」

5
dee

Ps -auxを使用すると、現在のプロセスが表示されます。これらはすべて/ proc /に/ proc /(pid)/としてリストされ、cat/proc /(pid)/ fd/0を呼び出すことで、標準出力にあるすべてのものを出力しますそのプロセスだと思う。おそらく、

/ proc /(pid)/ fd/0-標準出力ファイル
/proc /(pid)/ fd/1-標準入力ファイル
/proc /(pid)/ fd/2-標準エラーファイル

例えばmy terminal window

しかし、これは/ bin/bashに対してのみうまく機能しました。他のプロセスは通常0には何もありませんでしたが、多くは2

3
Sam

これらのファイルに関する信頼できる情報については、manページを確認し、ターミナルでコマンドを実行してください。

$ man stdout 

ただし、簡単な答えとして、各ファイルは次の目的に使用されます。

stdoutストリーム出力の場合

stdinストリーム入力用

stderr印刷エラーまたはログメッセージ用。

各UNIXプログラムには、これらのストリームが1つずつあります。

2
Margach Chris

stderrはIOキャッシュバッファリングを行わないので、アプリケーションが重要なメッセージ情報(エラー、例外)をコンソールまたはファイルに出力する必要がある場合、stdoutを使用して一般的なログ情報を印刷しますIOキャッシュバッファリングにより、メッセージをファイルアプリケーションに書き込む前に閉じる可能性があり、デバッグが複雑になる可能性があります。

2
geekanil

関連付けられたバッファリングを持つファイルはストリームと呼ばれ、定義されたタイプFILEへのポインタであると宣言されます。 fopen()関数は、ストリームの特定の記述データを作成し、以降のすべてのトランザクションでストリームを指定するポインターを返します。通常、ヘッダーで宣言され、標準のオープンファイルに関連付けられた定数ポインターを持つ3つのオープンストリームがあります。プログラムの起動時に、標準入力(従来の入力を読み取るため)、標準出力(従来の出力を書き込むため)、および標準エラー(診断出力を書き込むため)の3つのストリームが事前定義され、明示的に開く必要はありません。開いたとき、標準エラーストリームは完全にバッファリングされていません。標準入力および標準出力ストリームは、ストリームが対話型デバイスを参照しないと判断できる場合にのみ、完全にバッファリングされます

https://www.mkssoftware.com/docs/man5/stdio.5.asp

0