はじめに
「Linuxでコマンドをぶったたいてる時どっちが先だっけ?と迷うヤツ選手権」を開いたら、
恐らく、tarか/dev/nullへのリダイレクトが優勝すると思います。
ということで、今回は優勝候補の/dev/nullへのリダイレクトさんについて調べてみます。
順番間違ってても一見行けそうじゃん?と思うけど、実際はいけないんですよね。
そもそも1とか2とかリダイレクトって何
ところで1とか2とか訳も分からず使ってるけどなんだっけ…という人のために。
1とか2とかはファイルディスクリプタと呼ばれるものです。(以降FDと略します)
FDは「fd_arrayという配列にある、ファイルオブジェクトを指し示すポインタを指し示すポインタ」です。
…書いてて意味が分からないので、図に示します。
まぁ、背番号みたいなものです。
あー…名前分かんないけど、西武の背番号24番の人にこの荷物届けてください!
っていったらブコビッチに荷物がちゃんと届くようなもんです。
そして、FDの0は標準入力、1は標準出力、2は標準エラー出力と呼ばれています。
通常、プロセスがエラー以外のメッセージを出力するときは標準出力、
エラーメッセージを出力するときは標準エラー出力を利用します。
(意図的にエラーではないメッセージをエラー出力に出す時もあります)
例えば、lsに存在するファイルと存在しないファイルを引数として与えて実行した場合、
見つかったファイル一覧は標準出力にぶん投げ、「そんなファイル見当たらん!」という
エラーメッセージは標準エラー出力にぶん投げます。
どちらも、基本的にはディスプレイに出力されます。
しかしながら、必ずしもディスプレイに表示したいわけではなく、
たまにはコマンド結果をファイルに記録しておきたいこともあります。
エラーメッセージは邪魔だから、エラーメッセージのみ表示しないようにしたい場面もあります。
そういったとき、FDの指し示す先を変更する事をリダイレクトと呼びます。
1>/dev/null 2>&1の動き
では、ようやく話の中心です。
1>/dev/null 2>&1と2>&1 1>/dev/nullは何が違うのか。
前者はメッセージがすべて表示されなくなります。
後者はありがちな間違いで、エラーメッセージが表示されてしまいます。
前者はいいやつ、後者はだめなやつですね。
まずいいやつから見ていきます。
(実際はプロセスがcloneされるのですが、そこは割愛で)
まず最初に、/dev/nullを開きます。FD3が割り当たります。
次に、FD3を複製してFD1を作成します。つまり、FD1の参照先が/dev/nullに変わります。
そして、FD1を複製してFD2を作成します。つまり、FD2の参照先も/dev/nullに変わります。これが2>&1。
結果、めでたく標準出力と標準エラー出力が/dev/nullを向きました。
2>&1 1>/dev/nullの動き
だめなやつです。
まず最初に、FD1を複製してFD2を作成します。この時点で同じものを見ているので、意味ありません。これが2>&1。
次に、/dev/nullを開きます。FD3が割り当たります。
FD3を複製してFD1を作成します。FD1の参照先が/dev/nullに変わります。
結局、エラーメッセージが標準エラー出力から画面に出るだけです。
〆
ただのリダイレクトの話なのに、システムコールまで調べる羽目になりました。
動作的にはこうだろうな~、でもそれってどういう根拠で?
じゃあ調べよう…(ズブズブ
OSとかkernelとかファイルシステムとか考えた人はホント凄いですわ…。