コマンドがエラーを生成したときに何が起こるかを探ってみましょう。存在しないディレクトリの内容をリストし、その出力を peanuts.txt という名前のファイルにリダイレクトしてみてください。
ls /fake/directory > peanuts.txt
クリーンなプロンプトの代わりに、画面にエラーメッセージが表示されます。
ls: cannot access /fake/directory: No such file or directory
なぜこのメッセージがファイルに送信されなかったのか疑問に思うかもしれません。これは、別の I/O ストリームである標準エラー、またはstderrが関係しているためです。
Linux における標準エラー (Standard Error) とは?
Linux では、stderr はプログラムがエラーメッセージや診断情報を送信するために使用するデフォルトの出力ストリームです。これは、通常のプログラム出力に使用される標準出力 (stdout) ストリームとは完全に分離されています。デフォルトでは、stdout と stderr の両方が出力をターミナル画面に送信するため、エラーメッセージが直接表示されます。
stderr を制御するには、別のリダイレクト方法が必要です。
ファイルディスクリプタの理解
stdin、stdout、stderr のような I/O ストリームを管理するために、システムはファイルディスクリプタを使用します。ファイルディスクリプタとは、カーネルがオープンされたファイルやストリームを識別するために使用する非負の数値です。デフォルトのファイルディスクリプタは次のとおりです。
0: stdin (標準入力)1: stdout (標準出力)2: stderr (標準エラー)
The number 2 is the dedicated stderr file descriptor, and we can use it to control where error messages go.
stderr をファイルにリダイレクトする
stderr をファイルにリダイレクトするには、ファイルディスクリプタ 2 の後に > 演算子を使用します。このコマンドは、すべてエラーメッセージを指定された stderr file に送信します。
ls /fake/directory 2> peanuts.txt
これで、ターミナルは静かになり、エラーメッセージは peanuts.txt の中に入ります。
stdout と stderr の結合
通常の出力とエラーメッセージの両方を同じファイルにキャプチャしたい場合はどうでしょうか?両方のストリームをリダイレクトすることで実現できます。
ls /fake/directory /etc/passwd > peanuts.txt 2>&1
これを分解してみましょう。
> peanuts.txtはstdout(ファイルディスクリプタ 1) をpeanuts.txtファイルにリダイレクトします。2>&1はstderr(ファイルディスクリプタ 2) を、現在stdout(ファイルディスクリプタ 1) が指しているのと同じ場所にリダイレクトします。
順序は重要です。2>&1 は stderr を stdout の現在の宛先に送信します。この場合、stdout はファイルを参照しているため、stderr もそのファイルに送信されます。
stdout と stderr の両方をリダイレクトする、よりモダンで短い方法は &> を使用することです。
ls /fake/directory /etc/passwd &> peanuts.txt
エラーメッセージの破棄
場合によっては、コマンドを実行し、発生する可能性のあるエラーメッセージを完全に無視したいことがあります。これを行うには、stderr を /dev/null という特別なファイルにリダイレクトします。これは、そこに書き込まれたデータを破棄します。
ls /fake/directory 2> /dev/null
このコマンドは実行され、stderr からのエラー出力は /dev/null に送信されて破棄されるため、画面はクリーンなままになります。