標準ストリーム
標準ストリーム(standard streams)とは,Unix系OS において,プログラムの活動実体であるプロセスとその実行環境の間でやり取りされる データの通り道(入出力チャネル) のことです.特に,キーボードからの入力を標準入力,ディスプレイへの出力を標準出力と呼びます.
多くのコマンドは,何も指定しなくても実行結果をディスプレイに表示しますが,これは標準出力としてディスプレイを使うことが デフォルトとして設定されているためです.
| 名称 | ファイル記述子 | 方向 | 主な用途 | 
|---|---|---|---|
| 標準入力 (stdin) | 0 | 入力 | キーボードや他プログラムの出力からデータを受け取る | 
| 標準出力 (stdout) | 1 | 出力 | 通常の結果やメッセージを出力する | 
| 標準エラー出力 (stderr) | 2 | 出力 | エラーメッセージなどを出力する | 

stdour,stderrのストリームが別れていることのメリット
標準出力(stdout) は,通常の処理結果やプログラムの出力を表します. これをリダイレクトしたりパイプで別のコマンドに渡した場合, 出力内容がファイルや別のコマンドへ送られるため,端末上には表示されません.
標準エラー出力(stderr) は,エラーメッセージや警告を伝えるための専用ストリームとなっています. 通常のリダイレクト(CMD > file1 など)では stderr はリダイレクトされず,端末画面にそのまま表示されます. そのため,
- ユーザーは標準出力をファイルや他の処理系に渡していても,エラーメッセージを見落とすことなく確認できる
- ログ処理とエラー監視を独立して制御できる
リダイレクト
- 標準出入力先を変更する機能のことをリダイレクトといいます
- 標準出入力とリダイレクトを理解することで,コマンドがどこに出力するのかをコントロールできます
Example 1 (Bash 標準ストリームのリダイレクト一覧) 
| 構文 | 意味 | 
|---|---|
| < FileA | 標準入力を FileA に変更 | 
| > FileA | 標準出力を FileA に変更(上書き) | 
| >> FileA | 標準出力を FileA の末尾に追記 | 
| 2> FileA | 標準エラー出力を FileA に変更(上書き) | 
| 2>> FileA | 標準エラー出力を FileA の末尾に追記 | 
| > FileA 2>&1 | 標準出力と標準エラー出力をまとめて FileA に変更 | 
| &> FileA | 標準出力と標準エラー出力をまとめて FileA に変更 | 
| 2>&1 | 標準エラー出力(stderr)を標準出力(stdout)の現在の設定にリダイレクト | 
| 2>&1 1> /dev/null | ラーを標準出力,標準出力を /dev/nullに捨てる | 
というメリットがあります.
/dev/null ファイル
Linux系OSでは /dev/null という疑似デバイスファイルを用意してあります. /dev/null に書き込まれたデータはすべて破棄され,どこからどれだけ読み込んでも何もデータを返しません.
エラーメッセージのみ出力させたくない場合は
echo 'stderr' 2> /dev/nullとしたりします.
<< EOF という似て非なるヒアドキュメント構文
command <<EOF
... 任意のテキスト ...
EOF- <<EOFは「この後に続く行を,- EOFが現れるまで標準入力として command に渡す」という意味
- <<EOFでなくても- <<WORDや- <<INPUTとしても良いですが,慣例的に- EOFが使われる
パイプ
- コマンドによって得られた結果を別コマンドに引き渡す機能のこと
- 通常では標準エラー出力(STDERR)はパイプされない
CMD1 の実行結果を CMD2 の標準入力に渡す場合
CMD1 | CMD2標準出力と標準エラー出力をまとめてパイプで渡したい場合は,2>&1 |,または |& を用います.
## 標準エラー出力用のパイプ
sed |& wc -l
## ファイル記述子とパイプの組み合わせ
sed 2>&1 | wc -l標準データストリーム,リダイレクト,パイプの実践
CASE 1: FileAの内容を並び替えて,その結果を別のファイルFileBに保存する
sort < FileA > FileB- sortコマンドは FileA の内容を読み取り(- < FileA)
- sortコマンドを実行し,並び替えを行う
- その結果を FileBに出力(> FileB)
ただし,同じ動作は
sort FileA > FileBでも達成できます.
CASE 2: エラーメッセージのみ出力させる
ユーザーがリダイレクトを用いて設定しなくては行けないことは
- 標準出力結果を /dev/nullへ捨てる
- 標準エラー出力を標準出力へ渡す
の2点となるので,以下の①と④を組み合わせて設定すればよいですが,設定順序がポイントなります.
| Index | 目的 | コマンド例 | 意味 | 
|---|---|---|---|
| ① | 標準出力を捨てる | CMD > /dev/nullCMD 1> /dev/null | 結果は捨てるが、エラーは表示 | 
| ② | 標準エラーを捨てる | CMD 2> /dev/null | エラーだけ捨てる | 
| ③ | 標準出力・標準エラーを両方捨てる | CMD &> /dev/nullCMD > /dev/null 2>&1 | すべての出力を破棄 | 
| ④ | 標準エラーを標準出力へ渡す | CMD 2>&1 | 両者を一緒に処理(例:パイプでまとめる) | 
正しい設定例
まず正しい例は
CMD1 2>&1 1> /dev/nullBashはリダイレクトを左から右へ順に評価するため,先にエラーを標準出力に結合し,次に出力を破棄という設定順番になります.
誤った設定例
CMD 1> /dev/null 2>&1だと,先に標準出力を破棄,次にエラーを現在の標準出力設定に結合になるので,標準出力及び標準エラー出力両方が /dev/null に捨てられてしまいます.
Example 2 (poetryで標準エラー出力のみを表示する場合) 
poetry コマンドを用いるときなど,標準出力結果には興味がないがエラーだけ知りたいという場合があります.この場合は
poetry update 1> /dev/null
poetry update > /dev/null
poetry update 2>&1 1> /dev/nullのいずれかの実行で標準エラー出力のみを表示することができます.最後の設定は標準エラー出力を標準出力にリダイレクトしているので, 厳密には挙動は同じではないことに注意してください.
CASE 3: ファイルへの書き込みと標準出力を同時に行う
tee コマンドを使うと標準出力を保持しつつファイルにも書き込むことができます.
tee コマンド
- teeコマンドは,標準入力から読み込んだデータを標準出力とファイルの両方に出力するコマンド- CMD | tee ファイル名
- デフォルトは上書き挙動だが, - -aオプションを付与することで追記(append)設定も可能
Example 3 
/etc/passwd ファイルの内容に行番号を付け,その結果をパイプを通してファイルへ出力し,さらにその結果をパイプでheadコマンドに渡す場合は
$ nl /etc/passwd | tee test.txt | head -3
     1  root:x:0:0:root:/root:/usr/bin/zsh
     2  daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
     3  bin:x:2:2:bin:/bin:/usr/sbin/nologinExample 4 (エラーを端末に表示しつつファイルに書く) 
標準出力を /dev/null に流しながら,標準エラー出力をファイルに書きたい場合は
CMD 1> /dev/null 2> error.logで十分ですが,これだと端末にエラー出力が表示されません.標準エラー出力表示を維持したい場合は,Bashのプロセス置換 >(...) を用いて
CMD 1> /dev/null 2> >(tee error.log)と記述します.