重要なポイント
- Linux コマンドは、コマンドに関するデータの転送に使用できる 3 つのデータ ストリーム (stdin、stdout、および stderr) を作成します。
- Linux では、stdin は入力ストリーム、stdout は出力ストリーム、stderr はエラー ストリームです。
- リダイレクトを使用すると、出力またはエラーをファイルやパイプなどの別の宛先にリダイレクトできます。
stdin
、
stdout
、および
stderr
、Linux コマンドの起動時に作成される 3 つのデータ ストリームです。これらを使用すると、スクリプトがパイプ処理されているかリダイレクトされているかを知ることができます。その方法をご紹介します。
ストリームは 2 つの点を結合します
Linux や Unix 系オペレーティング システムについて学び始めるとすぐに、
stdin
、
stdout
、および
stederr
という用語に遭遇するでしょう。これらは、Linux コマンドの実行時に確立される
3 つの標準ストリーム
です。コンピューティングにおいて、ストリームとはデータを転送できるものです。これらのストリームの場合、そのデータはテキストです。
データ ストリームには、水の流れと同様に 2 つの端があります。それらにはソースと流出があります。使用している Linux コマンドはいずれも、各ストリームの一端を提供します。もう一方の端は、コマンドを起動したシェルによって決まります。その端は、コマンドを起動したコマンド ラインに応じて、ターミナル ウィンドウに接続されるか、パイプに接続されるか、ファイルまたは他のコマンドにリダイレクトされます。
Linux 標準ストリーム: stdin、stdout、stderr
Linux では、
stdin
が標準入力ストリームです。これはテキストを入力として受け入れます。コマンドからシェルへのテキスト出力は、
stdout
(標準出力) ストリーム経由で配信されます。コマンドからのエラー メッセージは、
stderr
(標準エラー) ストリームを通じて送信されます。
したがって、2 つの出力ストリーム
stdout
と
stderr
と 1 つの入力ストリーム
stdin
があることがわかります。エラー メッセージと通常の出力にはそれぞれ、ターミナル ウィンドウに送信するための独自のコンジットがあるため、相互に独立して処理できます。
ストリームはファイルと同様に処理されます
Linux のストリームは、他のほとんどすべてのものと同様に、ファイルであるかのように扱われます。ファイルからテキストを読み取ることも、ファイルにテキストを書き込むこともできます。これらのアクションには両方ともデータのストリームが関係します。したがって、データのストリームをファイルとして処理するという概念は、それほど無理のあるものではありません。
プロセスに関連付けられた各ファイルには、それを識別するための一意の番号が割り当てられます。これはファイル記述子として知られています。ファイルに対してアクションを実行する必要がある場合は常に、 ファイル記述子を 使用してファイルを識別します。
これらの値は、
stdin
、
stdout,
および
stderr
に常に使用されます。
- 0: 標準入力
- 1: 標準出力
- 2: 標準エラー
パイプとリダイレクトへの反応
主題への入門を容易にするための一般的なテクニックは、その主題の簡略化されたバージョンを教えることです。たとえば、文法では、「E の前には I、C の後は除く」というルールがあると言われます。しかし実際には、 この規則に従うケースよりも例外の方が多いのです 。
同様に、
stdin
、
stdout
、および
stderr
について話すとき、プロセスは 3 つの標準ストリームがどこで終了するかは知らないし気にもしない、という一般に受け入れられている公理を持ち出すのが便利です。プロセスは、その出力が端末に送られるのか、それともファイルにリダイレクトされるのかを気にする必要があるでしょうか?入力がキーボードから来ているのか、それとも別のプロセスからパイプで入力されているのかさえわかりますか?
実際、プロセスは知っています — あるいは、チェックすることを選択した場合には少なくとも知ることができます — そして、ソフトウェア作成者がその機能を追加することを決定した場合には、それに応じて動作を変更できます。
この行動の変化は非常に簡単に確認できます。次の 2 つのコマンドを試してください。
ls
ls |猫
ls コマンドの出力 (
stdout
) が別のコマンドにパイプされる場合、
ls
コマンドの動作は異なります。単一列出力に切り替えるのは
ls
であり、
cat
によって実行される変換ではありません。そして、出力がリダイレクトされている場合、
ls
同じことを行います。
ls > キャプチャ.txt
猫の捕獲.txt
stdout と stderr のリダイレクト
エラー メッセージを専用のストリームで配信することには利点があります。これは、コマンドの出力 (
stdout
) をファイルにリダイレクトしても、ターミナル ウィンドウにエラー メッセージ (
stderr
) が表示されることを意味します。必要に応じて、エラーが発生したときに対処できます。また、エラー メッセージが
stdout
出力のリダイレクト先のファイルを汚染することも防ぎます。
次のテキストをエディタに入力し、error.sh というファイルに保存します。
#!/bin/bash
echo "About to try to access a file that doesn't exist"
cat bad-filename .txt
次のコマンドを使用してスクリプトを実行可能にします。
chmod +x エラー.sh
スクリプトの最初の行は、
stdout
ストリーム経由でテキストを端末ウィンドウにエコーします。 2 行目は、存在しないファイルへのアクセスを試行します。これにより、
stderr
経由で配信されるエラー メッセージが生成されます。
次のコマンドでスクリプトを実行します。
./error.sh
出力ストリーム
stdout
と
stderr
が両方とも端末ウィンドウに表示されていることがわかります。
出力をファイルにリダイレクトしてみましょう。
./error.sh > Capture.txt
stderr
経由で配信されるエラー メッセージは、引き続きターミナル ウィンドウに送信されます。ファイルの内容をチェックして、
stdout
出力がファイルに送信されたかどうかを確認できます。
猫の捕獲.txt
stdin
からの出力は期待どおりにファイルにリダイレクトされました。
>
リダイレクト シンボルは、デフォルトで
stdout
で機能します。数値ファイル記述子の 1 つを使用して、どの標準出力ストリームをリダイレクトするかを指定できます。
stdout
を明示的にリダイレクトするには、次のリダイレクト命令を使用します。
1>
stderr
を明示的にリダイレクトするには、次のリダイレクト命令を使用します。
2>
もう一度テストしてみましょう。今回は
2>
使用します。
./error.sh 2> キャプチャ.txt
エラー メッセージはリダイレクトされ、
stdout
echo
メッセージが端末ウィンドウに送信されます。
Capture.txt ファイルの内容を見てみましょう。
猫の捕獲.txt
stderr
メッセージは、予想どおり、capture.txt にあります。
stdout と stderr の両方をリダイレクトする
確かに、
stdout
または
stderr
を互いに独立してファイルにリダイレクトできる場合、両方を同時に 2 つの異なるファイルにリダイレクトできるはずです。
はい、できます。このコマンドは、
stdout
Capture.txt というファイルに送信し、
stderr
error.txt というファイルに送信します。
./error.sh 1> Capture.txt 2> error.txt
標準出力と標準エラーの両方の出力ストリームがファイルにリダイレクトされるため、ターミナル ウィンドウには出力が表示されません。何も起こらなかったかのようにコマンド ライン プロンプトに戻ります。
各ファイルの内容を確認してみましょう。
猫の捕獲.txt
猫のエラー.txt
stdout と stderr を同じファイルにリダイレクトする
すばらしいですね。各標準出力ストリームが独自の専用ファイルに送られるようになりました。他にできる唯一の組み合わせは、
stdout
と
stderr
の両方を同じファイルに送信することです。
これは次のコマンドで実現できます。
./error.sh > Capture.txt 2>&1
それを詳しく見てみましょう。
- ./error.sh: error.sh スクリプト ファイルを起動します。
-
> Capture.txt:
stdout出力ストリームを Capture.txt ファイルにリダイレクトします。>1>の短縮形です。 -
2>&1: &> リダイレクト命令を使用します。この命令を使用すると、あるストリームが別のストリームと同じ宛先に到達するようにシェルに指示できます。この場合、「ストリーム 2 (
stderrを、ストリーム 1 (stdout) がリダイレクトされているのと同じ宛先にリダイレクトする」と言っています。
目に見える出力はありません。それは励みになります。
Capture.txt ファイルをチェックして、その内容を確認してみましょう。
猫の捕獲.txt
stdout
と
stderr
ストリームの両方が 1 つの宛先ファイルにリダイレクトされました。
ストリームの出力をリダイレクトしてサイレントに破棄するには、出力を
/dev/null
に送信します。
スクリプト内のリダイレクトの検出
いずれかのストリームがリダイレクトされているかどうかをコマンドがどのように検出し、それに応じて動作を変更するかを選択できる方法について説明しました。独自のスクリプトでこれを実現できますか?はい、できます。そして、それは理解して採用するのが非常に簡単なテクニックです。
次のテキストをエディタに入力し、input.sh として保存します。
#!/bin/bash
if [ -t 0 ] ; then
echo stdin coming from keyboard
else echo stdin coming from a pipe or a file
fi
次のコマンドを使用して実行可能にします。
chmod +x input.sh
賢い部分は
角括弧内のテスト
です。ファイル記述子に関連付けられたファイルが
ターミナル ウィンドウで終了する
場合、
-t
(ターミナル) オプションは true (0) を返します。ファイル記述子 0 をテストの引数として使用しました。これは
stdin
を表します。
stdin
端末ウィンドウに接続されている場合、テストは true であることがわかります。
stdin
ファイルまたはパイプに接続されている場合、テストは失敗します。
便利なテキスト ファイルを使用して、スクリプトへの入力を生成できます。ここでは、dummy.txt というファイルを使用しています。
./input.sh < ダミー.txt
出力は、入力がキーボードからではなくファイルから来ていることをスクリプトが認識していることを示しています。必要に応じて、スクリプトの動作をそれに応じて変更できます。
これはファイル リダイレクトを使用したものでした。パイプを使用して試してみましょう。
猫のダミー.txt | ./input.sh
スクリプトは、入力がパイプされていることを認識します。より正確に言えば、
stdin
ストリームが端末ウィンドウに接続されていないことを再度認識します。
パイプもリダイレクトも使用せずにスクリプトを実行してみましょう。
./input.sh
stdin
ストリームはターミナル ウィンドウに接続され、スクリプトはそれに応じてこれを報告します。
出力ストリームで同じことを確認するには、新しいスクリプトが必要です。エディターに次を入力し、output.sh として保存します。
#!/bin/bash
if [ -t 1 ] ; then
echo stdout is going to the terminal window
else
echo stdout is being redirected or piped
fi
次のコマンドを使用して実行可能にします。
chmod +x input.sh
このスクリプトに対する唯一の重要な変更は、角括弧内のテストです。
stdout
のファイル記述子を表すために数字 1 を使用しています。
試してみましょう。出力を
cat
経由でパイプ処理します。
./出力 |猫
スクリプトは、その出力が端末ウィンドウに直接送信されないことを認識します。
出力をファイルにリダイレクトしてスクリプトをテストすることもできます。
./output.sh > Capture.txt
ターミナル ウィンドウには何も出力されず、何も言わずにコマンド プロンプトに戻ります。予想どおりです。
Capture.txt ファイル内を調べて、何がキャプチャされたかを確認できます。これを行うには、次のコマンドを使用します。
猫の捕獲.sh
繰り返しますが、スクリプトの簡単なテストでは、
stdout
ストリームが端末ウィンドウに直接送信されていないことが検出されます。
パイプやリダイレクトを使用せずにスクリプトを実行すると、
stdout
がターミナル ウィンドウに直接配信されていることを検出できるはずです。
./output.sh
そしてそれはまさに私たちが見ているものです。
意識の流れ
スクリプトがターミナル ウィンドウやパイプに接続されているか、リダイレクトされているかを判断する方法を知っていれば、それに応じてスクリプトの動作を調整できます。
ログ出力と診断出力は、出力が画面に出力されるかファイルに出力されるかに応じて、多かれ少なかれ詳細になります。エラー メッセージは、通常のプログラム出力とは別のファイルに記録されることがあります。
通常のことですが、知識が増えると選択肢も増えます。





