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


230

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

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


36
観察:この質問は2010年には受け入れ可能でしたが、最近は非常に迅速に反対票が投じられます。
byxor 2017

3
@ブランドン理由を教えてもらえますか?あなたのコメントには貴重だと思います。
独立した

3
@byxorは公平を期すために、私は質問します。opの投稿では、コードのデバッグを手伝ってくれる人を求めていましたか?Shouvikがstdin、stdout、およびstderrの目的について質問したようです。オペレーションの投稿は好奇心から外れているようです、違いますか?(私は実際にこれについて自分で学習しています。ありがとう、SO、この投稿を削除しなかったことを感謝します)
sansae

2
@ user123456正解です。私はソフトウェア開発者になることを学び、当時S / Oはプログラミングについて学ぶのに最適な場所でした。私たちは当初、これをすべての質問コンピューティングサイエンス向けのwikiサービスにすることを意図していました。#juniorDevForLife
Shouvik

3
@Shouvikの歴史に少し感謝します。私はソフトウェア開発者になる方法も学んでいます(sfのクールなキャンプに受け入れられました)。私はまだS / Oにかなり慣れていないので、投稿できるものとできないものについてはまだわかりません。ここでのモデレーションは非常に厳しい場合があります。私はそのハッシュタグが好きです。#juniorDevForLife。これはディスカッションに何も追加しないので、ここでコメントする代わりにpmをお願いしますが、S / Oにpmシステムがあるとは思いません。すてきな一日を。
sansae

回答:


251

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

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

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

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

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

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

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

例は次のとおりです。

my_prog <inputfile 2>errorfile | grep XYZ

これは:

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

あなたのコメントを再:

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

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

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

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


1
それはあなたの応答です。ファイルの目的はあなたの説明から理解できますが、レベルをさらに上げたいと思います。/ devフォルダーでこれらのファイルを開くと、実行中のプロセスの出力が表示されません。ターミナルでtopを実行するとします。その結果をstdoutファイルに定期的に出力することは想定されていないため、更新されると、このファイルに出力の出力のインスタンスが表示されるはずです。しかし、これはそうではありません。これらのファイルは同じではありません(/ devディレクトリにあるファイル)。
Shouvik

7
それらは技術的にはファイルではないからです。これらはデバイスノードであり、書き込む特定のデバイスを示します。UNIXはすべてをファイルの抽象化として提示するかもしれませんが、それは最も深いレベルではそうしません。
paxdiablo 2010

1
シェルリダイレクト機能を使用します。xyz >xyz.out他のプロセスで読み取ることができる物理ファイルに標準出力を書き込みます。stdoutをstdinに直接直接xyz | grep something接続します。そのように制御しないプロセスへの自由なアクセスが必要な場合は、なんらかの方法でカーネルにフックして出力をフィルタリングするようなコードを記述するか、コードを記述する必要があります。他の解決策もあるかもしれませんが、それらはおそらく互いに同じくらい危険です:-)xyzgrep/proc
paxdiablo

20
@Shouvik、これ/dev/stdinはへのシンボリックリンクであることに注意してください/proc/self/fd/0-現在実行中のプログラムが開いている最初のファイル記述子。したがって、常に「現在実行中のプログラム」を指す/dev/stdinので/proc/self/、ポイントされる対象はプログラムによって異なります。(どのプログラムがopen呼び出しを行っているかに/dev/stdin関係ありません。)setuidシェルスクリプトをより安全にするために友人たちがそこに置かれ、ファイル/dev/stdinだけを操作するプログラムにファイル名を渡して、よりインタラクティブに制御したいとしました。(いつかこれはあなたが知るのに役立つトリックになるでしょう。:)
sarnold

1
@ CarlosW.Mercado、ファイルはデータの物理的な表現です。たとえば、ハードディスクに保存されているビット。ファイルハンドルは、(通常)ファイルを開いた後、そのファイルを参照するために使用される小さなトークンです。
paxdiablo 2018

62

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

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


ご入力いただきありがとうございます。プロセスの出力データストリームを傍受し、それを自分のファイルに出力する方法を知っているでしょうか?
Shouvik 2010

51

上記の回答を補足するものとして、リダイレクトについて以下にまとめます。 リダイレクトのチートシート

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

図は2>&1が&>と同じ効果を持つことを示しています

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

4
あなたのコメントと承認された回答を組み合わせると、完璧に理解でき、明確に説明できます!ありがとう!
Mykola

1
写真は千の言葉に値する!
tauseef_CuriousGuy

22

あなたの理解は完全に逆です。:)

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

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

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

「標準の」ファイルが入力を読み取るために必要がある場合に使用して、使用されているfreadfgets、または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つあります。1つ目は、「標準入力」、「標準出力」、および「標準エラー」は単なる慣例です。これらは非常に強力な規則ですgrep echo /etc/services | awk '{print $2;}' | sortが、このようなプログラムを実行できることは非常に素晴らしいことであり、各プログラムの標準出力をパイプライン内の次のプログラムの標準入力に接続することができます。

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


したがって、プロセスが実行されているときに、このstderrファイルにエラーが書き込まれるとき、またはプログラムがそのソースからコンパイルされているときです。また、コンパイラの観点からこれらのファイルについて話すとき、プログラムと比較するときとは異なりますか?
Shouvik 2010

1
@Shouvik、コンパイラは、独自のstdin、stdout、およびstderrを備えた別のプログラムです。コンパイラーが警告またはエラーを書き込む必要がある場合、それらはstderrに書き込まれます。コンパイラーのフロントエンドがアセンブラーの中間コードを出力するとき、それはstdoutに中間コードを書き込み、アセンブラーはstdinにその入力を受け入れる可能性がありますが、ユーザーとしての観点からはすべてが裏で行われます。)コンパイルされたプログラムの場合、そのプログラムは標準エラーにエラーを書き込むこともできますが、コンパイルされることとは関係ありません。
sarnold、2010

その情報のトークンをありがとう。とにかくその視点でそれを見ないのは私にとってかなり愚かなことだと思います...:P
Shouvik

1
つまり、標準はプログラムを印刷するのに役立つと言っています
babygame0ver

9

stdin

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

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

stdout

コンソールに出力を生成します。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標準エラー出力をリダイレクトすることが可能2>


8

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

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

歴史的根拠についてはこれを見てください:

「すべてのプログラムが診断を標準出力に配置しました。これは、出力がファイルにリダイレクトされるときに常に問題を引き起こしていましたが、出力が疑いのないプロセスに送信されると耐えられなくなりました。それにもかかわらず、標準入力の単純さに違反したくありません標準出力モデルでは、人々はこの状況をv6まで許容していました。その後すぐに、Dennis Ritchieが標準エラーファイルを導入してGordianの結び目を切りました。これでは十分ではありませんでした。自分を識別するために」


3

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

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

例えばターミナルウィンドウ

しかし、これが/ bin / bashに対してのみうまく機能した場合、他のプロセスは一般的に0には何もありませんでしたが、多くは2でエラーが書き込まれていました


3

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

$ man stdout 

しかし、簡単な答えとしては、各ファイルは次のようなものです。

ストリームアウトの標準出力

ストリーム入力のstdin

エラーまたはログメッセージを出力するためのstderr

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


2

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


0

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.