Linuxのstdin、stdout、およびstderrとは何ですか?

公開: 2022-01-29
Linuxコンピュータのターミナルウィンドウ
Fatmawati Achmad Zaenuri / Shutterstock.com

stdinstdout 、およびstderrは、Linuxコマンドを起動したときに作成される3つのデータストリームです。 それらを使用して、スクリプトがパイプされているのかリダイレクトされているのかを判断できます。 その方法をお見せします。

ストリームが2つのポイントに参加

LinuxおよびUnixライクなオペレーティングシステムについて学び始めるとすぐに、 stdinstdout 、およびstederrという用語に出くわします。 これらは、Linuxコマンドの実行時に確立される3つの標準ストリームです。 コンピューティングでは、ストリームはデータを転送できるものです。 これらのストリームの場合、そのデータはテキストです。

水の流れのようなデータの流れには、2つの端があります。 それらには、ソースと流出があります。 使用しているLinuxコマンドは、各ストリームの一方の端を提供します。 もう一方の端は、コマンドを起動したシェルによって決定されます。 その端は、コマンドを起動したコマンドラインに従って、ターミナルウィンドウに接続されるか、パイプに接続されるか、ファイルまたは他のコマンドにリダイレクトされます。

Linux標準ストリーム

Linuxでは、 stdinが標準入力ストリームです。 これは、入力としてテキストを受け入れます。 コマンドからシェルへのテキスト出力は、 stdout (標準出力)ストリームを介して配信されます。 コマンドからのエラーメッセージは、 stderr (標準エラー)ストリームを介して送信されます。

したがって、 stdoutstderrの2つの出力ストリームと、 stdinの1つの入力ストリームがあることがわかります。 エラーメッセージと通常の出力にはそれぞれ、それらをターミナルウィンドウに運ぶための独自のコンジットがあるため、互いに独立して処理できます。

ストリームはファイルのように処理されます

Linuxのストリームは、他のほとんどすべてと同様に、ファイルであるかのように扱われます。 ファイルからテキストを読み取ったり、ファイルにテキストを書き込んだりできます。 これらのアクションは両方とも、データのストリームを含みます。 したがって、データのストリームをファイルとして処理するという概念は、それほど難しいものではありません。

広告

プロセスに関連付けられた各ファイルには、プロセスを識別するための一意の番号が割り当てられます。 これはファイル記述子として知られています。 ファイルに対してアクションを実行する必要がある場合は常に、ファイル記述子を使用してファイルを識別します。

これらの値は、常にstdinstdout,およびstderrに使用されます。

  • 0 :stdin
  • 1 :stdout
  • 2 :stderr

パイプとリダイレクトへの反応

誰かが主題を簡単に紹介できるようにするための一般的な手法は、トピックの簡略化されたバージョンを教えることです。 たとえば、文法では、ルールは「Cの後を除いてEの前にI」であると言われます。 しかし実際には、この規則に従う場合よりも多くの例外があります。

同様に、 stdinstdout 、およびstderrについて話すときは、プロセスが3つの標準ストリームがどこで終了するかを知らず、気にしないという受け入れられた公理を取り除くのが便利です。 プロセスは、その出力が端末に送られるのか、ファイルにリダイレクトされるのかを気にする必要がありますか? 入力がキーボードからのものなのか、別のプロセスからパイプされているのかさえわかりますか?

実際、プロセスは認識しており、少なくともチェックすることを選択した場合はそれを見つけることができます。ソフトウェアの作成者がその機能を追加することを決定した場合、プロセスはそれに応じて動作を変更できます。

広告

この振る舞いの変化は非常に簡単にわかります。 次の2つのコマンドを試してください。

 ls 

 ls | 猫

lsコマンドは、その出力( stdout )が別のコマンドにパイプされている場合、動作が異なります。 単一列の出力に切り替わるのはlsであり、 catによって実行される変換ではありません。 また、出力がリダイレクトされている場合、 lsは同じことを行います。

 ls> capture.txt 

 catcapture.txt 

stdoutとstderrのリダイレクト

専用ストリームによってエラーメッセージが配信されることには利点があります。 これは、コマンドの出力( stdout )をファイルにリダイレクトしても、ターミナルウィンドウにエラーメッセージ( stderr )が表示されることを意味します。 必要に応じて、エラーが発生したときに対応できます。 また、 stdoutがリダイレクトされたファイルをエラーメッセージが汚染するのを防ぎます。

次のテキストをエディターに入力し、error.shというファイルに保存します。

 #!/ bin / bash

echo "存在しないファイルにアクセスしようとしています"
猫bad-filename.txt

次のコマンドでスクリプトを実行可能にします。

 chmod + x error.sh

スクリプトの最初の行は、 stdoutストリームを介してテキストをターミナルウィンドウにエコーします。 2行目は、存在しないファイルにアクセスしようとします。 これにより、 stderrを介して配信されるエラーメッセージが生成されます。

次のコマンドでスクリプトを実行します。

 ./error.sh 

stdoutstderrの両方の出力ストリームがターミナルウィンドウに表示されていることがわかります。

出力をファイルにリダイレクトしてみましょう。

 ./error.sh> Capture.txt 

広告

stderrを介して配信されるエラーメッセージは、引き続きターミナルウィンドウに送信されます。 ファイルの内容をチェックして、 stdout出力がファイルに送信されたかどうかを確認できます。

 catcapture.txt 

stdinからの出力は、期待どおりにファイルにリダイレクトされました。

>リダイレクト記号は、デフォルトでstdoutで機能します。 数値ファイル記述子の1つを使用して、リダイレクトする標準出力ストリームを指定できます。

stdoutを明示的にリダイレクトするには、次のリダイレクト命令を使用します。

 1>

stderrを明示的にリダイレクトするには、次のリダイレクト命令を使用します。

 2>

もう一度テストしてみましょう。今回は2> :を使用します。

 ./error.sh 2> Capture.txt 

エラーメッセージがリダイレクトされ、 stdout echoメッセージがターミナルウィンドウに送信されます。

Capture.txtファイルの内容を見てみましょう。

 catcapture.txt 

stderrメッセージは期待どおりcapture.txtにあります。

stdoutとstderrの両方をリダイレクトする

確かに、 stdoutまたはstderrのいずれかを互いに独立してファイルにリダイレクトできる場合は、両方を同時に2つの異なるファイルにリダイレクトできるはずですか?

広告

はい、できます。 このコマンドは、 stdoutをcapture.txtというファイルに転送し、 stderrをerror.txtというファイルに転送します。

 ./error.sh 1> Capture.txt 2> error.txt 

出力のストリーム(標準出力と標準エラー)の両方がファイルにリダイレクトされるため、ターミナルウィンドウに表示される出力はありません。 何も起こらなかったかのように、コマンドラインプロンプトに戻ります。

各ファイルの内容を確認してみましょう。

 catcapture.txt
 cat error.txt 

stdoutとstderrを同じファイルにリダイレクトする

これはすばらしいことです。各標準出力ストリームは、専用のファイルに送られます。 私たちができる他の唯一の組み合わせは、 stdoutstderrの両方を同じファイルに送信することです。

これは、次のコマンドで実現できます。

 ./error.sh> Capture.txt 2>&1

それを分解しましょう。

  • ./error.sh:error.shスクリプトファイルを起動します。
  • > Capture.txtstdoutストリームをcapture.txtファイルにリダイレクトします。 >1>の省略形です。
  • 2>&1 :これは&>リダイレクト命令を使用します。 この命令を使用すると、あるストリームを別のストリームと同じ宛先に到達させるようにシェルに指示できます。 この場合、「ストリーム2、 stderrを、ストリーム1、 stdoutがリダイレクトされているのと同じ宛先にリダイレクトする」と言っています。

目に見える出力はありません。 それは励みになります。

Capture.txtファイルをチェックして、その内容を確認しましょう。

 catcapture.txt 

stdoutストリームとstderrストリームの両方が単一の宛先ファイルにリダイレクトされています。

ストリームの出力をリダイレクトしてサイレントに破棄するには、出力を/dev/nullに転送します。

スクリプト内のリダイレクトの検出

コマンドがストリームのいずれかがリダイレクトされているかどうかを検出し、それに応じてその動作を変更する方法を説明しました。 独自のスクリプトでこれを達成できますか? はい、できます。 そして、それは理解して採用するのが非常に簡単なテクニックです。

広告

次のテキストをエディターに入力し、input.shとして保存します。

 #!/ bin / bash

if [-t 0]; それから

  キーボードからのechostdin
 
それ以外

  パイプまたはファイルからのechostdin
 
fi

次のコマンドを使用して、実行可能にします。

 chmod + x input.sh

賢い部分は角括弧内のテストです。 -t (ターミナル)オプションは、ファイル記述子に関連付けられたファイルがターミナルウィンドウで終了した場合にtrue(0)を返します。 stdinを表すテストの引数としてファイル記述子0を使用しました。

stdinがターミナルウィンドウに接続されている場合、テストは真であることが証明されます。 stdinがファイルまたはパイプに接続されている場合、テストは失敗します。

便利なテキストファイルを使用して、スクリプトへの入力を生成できます。 ここでは、dummy.txtという名前を使用しています。

 ./input.sh <dummy.txt 

出力は、入力がキーボードからではなく、ファイルからのものであることをスクリプトが認識していることを示しています。 必要に応じて、スクリプトの動作を変更できます。

広告

それはファイルリダイレクトでした。パイプで試してみましょう。

 猫dummy.txt | ./input.sh 

スクリプトは、入力がパイプされていることを認識します。 または、より正確には、 stdinストリームがターミナルウィンドウに接続されていないことをもう一度認識します。

パイプもリダイレクトも使用せずにスクリプトを実行してみましょう。

 ./input.sh 

stdinストリームはターミナルウィンドウに接続されており、スクリプトはそれに応じてこれを報告します。

出力ストリームで同じことを確認するには、新しいスクリプトが必要です。 エディターに次のように入力し、output.shとして保存します。

 #!/ bin / bash

if [-t 1]; それから

エコーstdoutはターミナルウィンドウに行きます
 
それ以外

echostdoutがリダイレクトまたはパイプされています
 
fi

次のコマンドを使用して、実行可能にします。

 chmod + x input.sh

このスクリプトに対する唯一の重要な変更は、角括弧内のテストです。 stdoutのファイル記述子を表すために数字1を使用しています。

試してみましょう。 catを介して出力をパイプします。

 ./output | 猫

広告

スクリプトは、その出力がターミナルウィンドウに直接送信されないことを認識します。

出力をファイルにリダイレクトすることで、スクリプトをテストすることもできます。

 ./output.sh> Capture.txt 

ターミナルウィンドウへの出力はありません。コマンドプロンプトに静かに戻ります。 予想通り。

Capture.txtファイルの内部を調べて、何がキャプチャされたかを確認できます。 これを行うには、次のコマンドを使用します。

 猫capture.sh 

この場合も、スクリプトの簡単なテストで、 stdoutストリームがターミナルウィンドウに直接送信されていないことが検出されます。

広告

パイプやリダイレクトを使用せずにスクリプトを実行すると、 stdoutがターミナルウィンドウに直接配信されていることが検出されます。

 ./output.sh 

そしてそれはまさに私たちが見ているものです。

意識の流れ

スクリプトがターミナルウィンドウまたはパイプに接続されているか、リダイレクトされているかを判断する方法を知っていると、それに応じてスクリプトの動作を調整できます。

ロギングと診断出力は、画面に表示されるかファイルに表示されるかに応じて、多かれ少なかれ詳細になります。 エラーメッセージは、通常のプログラム出力とは異なるファイルに記録される可能性があります。

通常の場合と同様に、知識が増えると選択肢も増えます。

関連:開発者と愛好家のための最高のLinuxラップトップ