Linuxのシェルでコマンドを実行すると、通常の結果は標準出力、警告や失敗理由は標準エラー出力へ送られます。Bashでは標準入力がファイル記述子0、標準出力が1、標準エラー出力が2です。エラーだけをファイルへ保存する基本形は2> ファイル名ですが、>は既存ファイルを切り詰めるため、意味を理解せず実行すると大切なログを失います。本稿では表示先を安全に分ける方法、順序で結果が変わる理由、パイプと終了状態の確認までを扱います。
標準出力と標準エラーを見分ける
コマンドが何をどちらへ出すかは、そのプログラムの仕様です。画面に同じように表示されても、シェル内部では別の流れになっています。まず検証用ディレクトリで、存在するパスと存在しないパスを混ぜた読み取りコマンドを実行し、標準出力と標準エラーが発生する状況を観察します。本番の変更コマンドを使って試す必要はありません。リダイレクト記号はシェルが解釈するため、プログラム自身のオプションではありません。
ls -- /etc/hostname /path/that-does-not-exist
この例では、存在する項目は標準出力へ、見つからない項目の説明は標準エラーへ出るのが一般的です。ただし、表示文言やローカライズは環境で異なります。エラー文の文字列だけを解析して成功判定せず、終了状態を確認してください。メッセージの言語や版が変わっても、0は成功、0以外は失敗という規約をプログラムが採用していることが多い一方、grepの「一致なし」のように1が想定内の状態を表すコマンドもあります。対象コマンドのマニュアルが基準です。
エラーだけを新しいファイルへ保存する
標準エラーだけを保存するには、ファイル記述子2をリダイレクトします。保存先には案件名と日時を含む、存在しない新規ファイルを使うのが安全です。次の例では標準出力は画面に残り、標準エラーだけがファイルへ入ります。実行前にtest -eなどで同名ファイルがないことを確認する運用も有効です。
ls -- /etc/hostname /path/that-does-not-exist 2> command-20260716-1400.err
printf 'exit status: %s\n' "$?"
2>はコマンド開始前に保存先を開き、既存内容を空にします。保存先のパスを変数で作るときは引用し、空文字や改行、パストラバーサルを許さないでください。管理者権限でコマンドを実行していても、リダイレクトを行うのは外側のシェルなので、権限の評価主体が想定と違うことがあります。権限エラーを避けるために全員書き込み可能なディレクトリを使わず、専用ログディレクトリと所有権を整えます。
追記は2>>、ただし肥大化を管理する
既存ログの末尾へエラーを追加するには2>>を使います。過去の内容は保たれますが、無期限に追記すると容量を使い切り、複数実行が混ざって原因を追えなくなります。開始時刻、コマンド名、ジョブIDなどを別途記録し、logrotateやジョブ管理基盤の保持設定を使います。複数プロセスが同じファイルへ長い行を書けば、出力が交錯する可能性もあります。高頻度の本番処理ではsystemd journalや集中ログ基盤を優先します。
some_read_only_check 2>> application-check.err
status=$?
printf 'check status: %s\n' "$status"
標準出力と標準エラーを別ファイルにする
正常結果とエラーを分けたい場合は、それぞれファイル記述子1と2を別の新規ファイルへ向けます。ファイル記述子を省略した>は1>と同じです。監査やバッチ処理では、両方を残すと「何が出力され、何が失敗したか」を後で確認できます。保存先に個人情報やトークンが混ざる可能性があるため、作成時のumask、ディレクトリ権限、保管期限も設計します。
some_report_command > report-20260716.out 2> report-20260716.err
status=$?
printf 'report status: %s\n' "$status"
二つの出力を同じファイルにまとめる
標準出力と標準エラーを同じ記録へまとめる代表的な書き方は> combined.log 2>&1です。Bashには&> combined.logという短縮形もありますが、他のシェルへ移植するなら前者の方が意図を示しやすい場合があります。まとめると時系列を追いやすい一方、機械処理で正常値とエラーを分離しにくくなります。目的に合わせて選びます。
some_report_command > combined-20260716.log 2>&1
順序を逆にすると結果が変わる
Bashはリダイレクトを左から右へ処理します。>file 2>&1は、まず標準出力をファイルへ向け、次に標準エラーを「その時点の標準出力」と同じ場所へ向けます。対して2>&1 >fileは、先に標準エラーを現在の標準出力、通常は端末へ複製し、その後で標準出力だけをファイルへ変更します。見た目が似ていても同じではありません。
some_report_command > combined.log 2>&1
some_report_command 2>&1 > stdout-only.log
複雑なリダイレクトは一行で賢く書くより、標準出力用と標準エラー用に明示的なファイルを用意する方がレビューしやすいことがあります。既存スクリプトを変更するときは、ログ収集エージェント、cronメール、systemdのStandardOutput/StandardError、CIのログ表示が現在どの出力を受けているかも確認します。
/dev/nullへ捨てるのは限定的に使う
2>/dev/nullは標準エラーを破棄します。対話的な存在確認で、失敗自体を終了状態で処理し、メッセージが本当に不要な場合には使えます。しかし、自動処理や本番障害調査で無条件に捨てると、権限不足、容量不足、設定ミス、接続障害など重要な兆候が消えます。少なくとも終了状態を分岐し、想定外の失敗は監視可能なログへ残してください。標準出力まで捨てる>/dev/null 2>&1はさらに観測性を下げます。
if optional_probe 2>/dev/null; then
printf '%s\n' 'probe succeeded'
else
printf '%s\n' 'probe did not succeed' >&2
fi
この例も、失敗が「機能がない」という想定内状態なのか、通信障害などの異常なのかをoptional_probeの終了状態仕様に応じて分ける必要があります。単にtrue/falseへ丸めると、異なる原因が同じ扱いになります。
上書きを防ぐnoclobber
Bashのset -o noclobberを有効にすると、通常の>で既存の通常ファイルを上書きしにくくできます。ただし、>|で明示的に上書きできることや、すべての競合や特殊ファイル問題を解決する機能ではないことに注意します。スクリプトの途中で設定を変えると、呼び出し元やsourceされた処理へ影響する場合があります。サブシェルへ閉じ込める、終了時に状態を戻す、初めから一意な名前を生成するなど、設計で衝突を避けます。
(
set -o noclobber
some_report_command > new-report.log 2> new-report.err
)
teeで画面とファイルの両方へ出す
teeは標準入力を標準出力とファイルへ複製します。標準出力と標準エラーを結合してからteeへ渡せば、画面で見ながら保存できます。ただし、パイプラインの既定の終了状態は通常、末尾のteeの状態です。先頭コマンドが失敗してもteeが成功すれば、全体が成功に見えることがあります。Bashのset -o pipefailを使うか、PIPESTATUSを確認します。またteeも既定ではファイルを上書きし、-aで追記します。
set -o pipefail
some_report_command 2>&1 | tee combined-20260716.log
status=$?
printf 'pipeline status: %s\n' "$status"
pipefailは既存スクリプトの終了条件を変えるため、途中へ無計画に追加しません。各コマンドが「一致なし」などを非0で表す場合、期待した分岐を明示します。機密情報を画面とファイルの二箇所へ複製する点にも注意してください。CIログが外部サービスへ送られる環境では、teeによる表示が情報漏えいの経路になることがあります。
リダイレクト失敗もコマンド失敗になる
保存先ディレクトリがない、書き込み権限がない、ファイルシステムが読み取り専用、容量やinodeが不足している場合、シェルはコマンド本体を開始できないことがあります。アプリケーションのエラーだけでなく、シェルが出すリダイレクトエラーも確認します。保存先をネットワーク共有にすると、切断や遅延で処理自体へ影響することもあります。重要なジョブでは、実行前の容量確認、実行後のファイル存在・サイズ・終了状態、ログ収集の監視を組み合わせます。
実運用のチェックリスト
- 対象コマンドが標準出力、標準エラー、終了状態をどう定義しているか公式マニュアルで確認した。
- 保存先は専用ディレクトリで、既存ファイル名と衝突せず、必要な利用者だけが読める。
- 上書き、追記、分離、結合、破棄のうち、調査と監査に合う方法を選んだ。
- パイプラインでは先頭コマンドの失敗を見落とさず、想定内の非0状態を分けている。
- ログのローテーション、容量監視、保持期限、秘密情報のマスキング方針がある。
- テストでは読み取り専用コマンドとダミー保存先を使い、本番データを上書きしていない。
エラー出力のリダイレクトは記号一つで書けますが、安全性は保存先、上書き、終了状態、運用監視まで含めて決まります。まず2>、2>>、2>&1の意味と左から右の処理順序を理解し、短い検証コマンドで確認してから自動化へ入れてください。

コメント