この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
こういうトラブルを現場で何度も見てきました。
原因は、標準出力(stdout)と標準エラー出力(stderr)の違いを正しく理解していないことです。
この記事では、20年以上Linuxサーバーを運用してきた経験から、stdoutとstderrを正しく扱えるエンジニアが現場で信頼される理由と、cronやシェルスクリプトで必ず押さえておきたいリダイレクトの考え方を解説します。
この記事のポイント
・stdoutとstderrは別物、>だけではエラーは記録されない
・cronで「成功時だけ静かに動く」設計にはstderr分離が必須
・2>&1と&>の違いを理解すると障害調査が速くなる
・標準出力の思想を知ると、なぜUNIX哲学が強いかが見える
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜ標準出力と標準エラー出力は分かれているのか
Linuxには、プロセスが起動すると自動的に3つの入出力が割り当てられます。・標準入力(stdin / ファイル記述子0):キーボードやパイプからの入力
・標準出力(stdout / ファイル記述子1):処理の結果・正常なメッセージ
・標準エラー出力(stderr / ファイル記述子2):エラー・警告・診断メッセージ
なぜ「出力」を2つに分けているのか。
答えはシンプルで、「成功した結果」と「エラーメッセージ」を混ぜたくないからです。
たとえばfindコマンドで全ディレクトリを検索すると、権限がないディレクトリでは「Permission denied」が出ます。このエラーが検索結果と混ざると、後続のスクリプトが正しく動きません。だから結果はstdoutへ、エラーはstderrへ、という設計になっています。
UNIX哲学の「一つのことをうまくやる」「テキストを扱う」という思想を支えているのが、この出力の分離です。私のセミナーでも、ここを理解している受講生はシェルスクリプトの組み方が明らかに上達が速いと感じています。
現場で起きがちな「ログが残っていない」トラブル
ここからが本題です。受講生からよく聞かれる質問で、こんなものがあります。
「cronで毎日スクリプトを動かしているのに、エラーが起きているのに気づけませんでした。なぜですか?」
そのスクリプトの起動行を見ると、大抵こうなっています。
# NG例:stderrを捨てている 0 3 * * * /usr/local/bin/backup.sh > /var/log/backup.log
「>」という記号は、ファイル記述子1(stdout)だけをリダイレクトする指示です。エラーメッセージはstderr(ファイル記述子2)なので、これでは画面にもファイルにも残らず、cron経由だと管理者メール(ある場合)に飛ぶだけです。
「動いているつもり」が一番怖い、というのは別の記事でも書きましたが、その原因の多くはstdoutとstderrの分離設計を知らないことに起因します。
1. 正しいログの取り方
両方を1つのファイルに残すなら、以下のように書きます。# OK例:stderrもstdoutと同じファイルへ 0 3 * * * /usr/local/bin/backup.sh > /var/log/backup.log 2>&1
順序も重要で、「2>&1 > /var/log/backup.log」と書くと、stderrがリダイレクトされた時点ではstdoutはまだターミナルを指しているので、意図した動作になりません。> の後に 2>&1 を置く、これが鉄則です。
2. stdoutとstderrを別々のファイルに残す書き方
障害調査のとき、エラーだけを素早く見たいことがあります。その場合は、ファイルを分けます。
# 成功ログとエラーログを分離 0 3 * * * /usr/local/bin/backup.sh > /var/log/backup.log 2> /var/log/backup.err
3. bash限定の簡潔な書き方
bashや一部のシェルでは、両方をまとめるための短縮記法があります。# bashなら「&>」で両方を同じファイルへ 0 3 * * * /usr/local/bin/backup.sh &> /var/log/backup.log
ただし、これはbash/zshの拡張記法で、POSIX準拠のshやdashでは動作しません。cronのスクリプトを複数のOSで共通運用する場合は、移植性を優先して「> file 2>&1」の形を使うのが現場の定石です。
実務でよくあるリダイレクトの応用パターン
現場で特に使用頻度が高い3つのパターンを紹介します。1. エラーだけを捨てたいとき
findやgrepで権限エラーの「Permission denied」を画面に出したくないケースです。# stderrだけを/dev/nullへ find / -name "*.conf" 2> /dev/null
2. パイプの前後でエラーを失わない
「command1 | command2」の形でパイプを使うとき、パイプはstdoutしか渡しません。そのため、command1のエラーはcommand2に渡らず、ターミナルへそのまま出ます。command1のエラーもcommand2で処理したい場合は、先に2>&1でまとめます。
# エラーも含めてgrepしたい /usr/local/bin/backup.sh 2>&1 | grep -i error
3. teeでログ保存と画面表示を両立する
作業ログを残しながら手動で実行結果も確認したい、という場面では tee が活躍します。# 画面にも出しつつ/var/log/work.logにも保存 /usr/local/bin/deploy.sh 2>&1 | tee /var/log/work.log
stdout/stderrの設計を理解すると見えてくる世界
標準出力と標準エラー出力の違いは、単なる文法の話ではありません。UNIX哲学の「小さなツールを組み合わせる」という思想を支える根幹です。grepでもawkでもsedでも、コマンドは「結果はstdoutに、エラーはstderrに」という約束を守っているから、パイプで連結しても破綻しない。
私が現場でよく見かけるのが、独自ツールを書くときにこの約束を守らずにエラーをstdoutに混ぜてしまい、後続のパイプで意味不明なエラーになるパターンです。受講生にも、シェルスクリプトを書くときは「進捗メッセージはstderrへ、処理結果はstdoutへ」と指導しています。これを守るだけで、そのスクリプトは他人のパイプラインに組み込んでもらえる資産に変わります。
セミナーで3,100名以上を指導してきた中で、stdoutとstderrの違いを雑に扱っている人ほど、あるとき必ず大きなトラブルにぶつかる、というのが私の結論です。
本記事のまとめ
Linuxの標準出力と標準エラー出力の違いを押さえておくと、現場でのトラブル対応が一段深くなります。| やりたいこと | 書き方 |
|---|---|
| stdoutをファイルに残す | command > /var/log/out.log |
| stderrもまとめて残す | command > /var/log/out.log 2>&1 |
| stdoutとstderrを分けて残す | command > /var/log/out.log 2> /var/log/err.log |
| bashで両方をまとめる短縮形 | command &> /var/log/out.log |
| エラーだけ捨てる | command 2> /dev/null |
| ログ保存と画面表示を両立 | command 2>&1 | tee /var/log/work.log |
cronやシェルスクリプトを書くたびに「このリダイレクトでエラーは本当に残るか?」と自問する習慣をつけてください。このひと手間が、夜中に呼び出される障害を未然に防ぎます。
リダイレクトを使いこなせるエンジニアになりませんか?
stdoutとstderrを正しく扱う力は、Linuxサーバーの仕組みを正しく理解していることが土台になります。現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
登録10秒/合わなければ解除3秒 / 詳細はこちら
- 次のページへ:Git 2.54で追加された『git history』コマンドとは何か|git logとの違いを現役Linuxエンジニアが解説
- 前のページへ:Linuxエンジニアが「作業を戻せる状態」にこだわる理由|現役講師が教える可逆性という発想で事故を防ぐ
- この記事の属するカテゴリ:Linux学習ガイドへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。
登録無料・いつでも解除できます