No.495


【Linux】ファイルディスクリプタ【出力】

リダイレクトと標準出力、エラー出力の関係

 普段何気なく使っている 2>&1 。聞かれるたびにテキスト書くのも面倒くさくなってきたので、説明用にメモ。


ファイルディスクリプタ

 この '2' とか '1' の数字はUNIXシステム特有のもので、ファイルの種類を参照するキーであり、「ファイルディスクリプタ」と呼ばれる。

ファイルデスクリプタ

番号 意味 表記
0 標準入力 stdin
1 標準出力 stdout
2 標準エラー出力 stderr

 つまり1番は stdout であり、 echo コマンドなどの出力先となる。指定が無ければコンソールだし、パイプで渡せば他のコマンドの標準入力 stdin に渡すことができる。リダイレクトも同様。

echo 'test' ※コンソールに出力
echo 'test' | gzip ※gzipコマンドに標準入力として渡される

 2番は stderr であり、こちらはコンソール固定になる。こちらは標準出力と異なり、パイプで渡しても出力は引き継がれずコンソールに出力されてしまう。リダイレクトは通常通り動作する。

 つまり、リダイレクトで上手いこと標準出力と標準エラー出力を同じファイルに


リダイレクトの意味

 そういうわけでリダイレクトで標準エラー出力を拾うわけだが、標準出力と標準エラー出力を同じファイルに出力しようとすると、記載方法を間違えると問題が発生してしまう。

 正解は冒頭でも書いた 2>&1 だ。
 & の意味は「複製」であり、上記の意味は「2番を複製した1番に流す」となる。つまり「標準エラー出力を複製した標準出力に流す」ということになる。
 これにより、標準出力と標準エラー出力が順序よく同じファイルへと出力されてくれる。

script >logfile 2>&1

 注意が必要なのは 2>&1 の前に標準出力のリダイレクト >logfile を記載する必要があること。
 先に標準出力のリダイレクトを記述することでファイルディスクリプタ1番を定義し、その後に標準エラー出力のリダイレクトを設定する必要があるのだ。

 なお、下記のように両方記載すると同じ効果があるように思えるけど、これはNG。
 ファイルのロックなどの問題と思われるが、記載漏れが発生する可能性がある。

script >logfile 2>logfile ※NG例