今回はリダイレクトのお話です。
リダイレクトといっても、Http リダイレクトとは別です。
プログラムの入力元や出力先を通常とは違うものに変更することの方です。
実はこの話題については非常に苦い思い出があるので、深入りしたくないのですが・・・(笑)
画面に標準出力
例えば、シェルで以下のコマンドを入力してみます。
1 | $ echo rilakkuma |
コマンドの通り、画面に rilakkuma と表示されます。
通常 bash では標準出力はディスプレイ画面がデフォルトとなっています。
ファイルに標準出力
では、出力先をファイルに切り替えてみます。
1 | $ echo rilakkuma > output.txt |
上記のようにすると、画面には何も出力されません。
しかし output.txt の中身を cat などで見てみると、ファイルに rilakkuma という文字列が書き込まれているのがわかります。
1 2 | $ cat output.txt rilakkuma |
また、出力のリダイレクト記号を使うとファイルが新規として作成されます。
もしファイルに追記するかたちで出力結果を書き込みたいときは以下のようにします。
1 | $ echo korilakkuma >> output.txt |
運用中の使用例
例えば MySQL でデータベースを運用している場合、mysqldump などで出力先をファイルに切り替えて保存しておくケースが多いと思いますが、もしプログラムの実行途中でエラーが発生していたらエラーメッセージはどうなると思いますか?
そうです、ディスプレイに表示されます。
標準出力と標準エラー出力は別物なのです。
1 2 | $ cat input.txt > input2.txt cat: input.txt: No such file or directory |
標準出力も標準エラー出力もファイルに書き込みたい場合は、下記のような記号を使います。
1 2 3 4 | $ cat output.txt input.txt &> result.txt $ cat result.txt rilakkuma cat: input.txt: No such file or directory |
標準エラー出力を標準出力にリダイレクトさせる
標準エラー出力を標準出力にリダイレクトする場合は、以下のように表記します。
1 2 3 4 | $ cat output.txt input.txt > result.txt 2>&1 $ cat result.txt rilakkuma cat: input.txt: No such file or directory |
標準入力
ここまでは、出力のお話をしましたが、じゃあ入力もあるの?って疑問に思うと思います。
はい、あります。
標準入力は出力とは逆の記号を使います。
例えば、cat コマンドを単独で使うと、キーボードからの入力モードとなります。
1 2 3 4 | $ cat rilakkuma <-- キーボードから入力 rilakkuma <-- 画面に出力 Ctrl + D で終了 |
同じ要領で、先ほど作成した result.txt を入力元として試してみます。
1 2 3 | $ cat < result.txt rilakkuma cat: input.txt: No such file or directory |
標準入出力の割り当て
実はこの「標準出力」「標準エラー出力」「標準入力」は、最初から OS によって準備されています。
標準入力:0
標準出力:1
標準エラー出力:2
この 0~2 は、プログラムがアクセスするファイルや標準入出力などを OS が識別するために用いる識別子となります。
これらは一般的に「ファイルディスクリプタ」と呼ばれています。
何かのプログラムが新たにファイルをオープンすると 3 が割り当てられます。
シェルで意識するのは「標準出力」「標準エラー出力」「標準入力」
ってことでかなり基本的なお話ですが、使い方を間違えると危険な場合もあるのである程度理解しておかなければいけない部分です。
コマンドとしてはもっと複雑な書き方もできますが、そうなると bash のソースを追って挙動を理解できないと苦しいかも・・・。
実際にシェルなどのプログラムを使ってサーバを運用するときは、標準出力と標準エラー出力をうまく使い分けて実装していかなければいけません。
標準出力の結果ばかり気にしていると、密かに発生しているエラーに気付かないかもしれないからです。
cshの場合
ここまでは bash に特化した話でしたので csh についても補足しておきます。
補足というか使用しているレンタルサーバの OS が FreeBSD だったのでちょっと調べただけですが。
標準出力と標準エラー出力をともに同じファイルに出力する場合の方法です。
1 | $ cat output.txt input.txt >& result.txt |
ただ cron の実行が csh とは必ずしも限らないので、そこは注意が必要です。
crontab の先頭で下記のように書かれていると、csh で扱われたりします。
1 | SHELL=/bin/csh |