「パイプで処理をつなげているけど、途中経過を確認する方法がわからない」
サーバーの運用や構築作業で、こうした場面に出くわすことは日常的にあります。
この記事では、
tee コマンドの基本的な使い方から、-a オプションによる追記、パイプラインの途中でデータを分岐させるテクニック、sudo との組み合わせ、そしてログ保存の実務パターンまで解説します。RHEL 9.4 / Ubuntu 24.04 LTS で動作確認済みです。
この記事のポイント
・tee は標準入力を標準出力とファイルに同時出力するコマンド
・tee -a でファイルに追記、-a なしだと上書きされる
・sudo tee でroot権限が必要なファイルへの書き込みができる
・パイプラインの途中に挟んで処理の中間結果を保存できる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
teeコマンドとは?
tee は、標準入力から受け取ったデータを「標準出力(画面)」と「指定したファイル」の両方に同時に出力するコマンドです。名前の由来は、水道のT字管(T-piece)です。1本の流れを2方向に分岐させるイメージで、パイプラインの途中にデータの分岐点を作れます。
リダイレクト(
>)だけではファイルに書き出すと画面には表示されません。逆に画面で確認するだけではファイルに残りません。tee を使えば、その両方を同時にできます。基本的な使い方
1. コマンドの出力を画面とファイルに同時出力する
tee の最もシンプルな使い方は、パイプで前のコマンドの出力をつなげて、ファイルに書き出しながら画面にも表示するパターンです。# dfコマンドの出力を画面に表示しつつ、disk_usage.txt にも保存する $ df -h | tee disk_usage.txt Filesystem Size Used Avail Use% Mounted on /dev/sda1 50G 18G 30G 38% / tmpfs 3.9G 0 3.9G 0% /dev/shm /dev/sda2 200G 95G 96G 50% /data # ファイルに保存されたことを確認する $ cat disk_usage.txt Filesystem Size Used Avail Use% Mounted on /dev/sda1 50G 18G 30G 38% / tmpfs 3.9G 0 3.9G 0% /dev/shm /dev/sda2 200G 95G 96G 50% /data
2. teeを使わない場合との比較
リダイレクトだけだと、画面には何も表示されません。# リダイレクトだけの場合:画面には何も出ない $ df -h > disk_usage.txt # teeを使う場合:画面にも出る+ファイルにも保存される $ df -h | tee disk_usage.txt
tee の強みです。ファイルに追記する(tee -a)
3. -a オプションで既存ファイルに追記する
tee はデフォルトでファイルを上書きします。既存の内容を消さずに末尾に追記したい場合は、-a(append)オプションを使います。# 1回目:ファイルを新規作成 $ date | tee time_log.txt Tue Apr 15 10:30:45 JST 2026 # 2回目:-a なしだと上書きされる $ date | tee time_log.txt Tue Apr 15 10:31:02 JST 2026 $ cat time_log.txt Tue Apr 15 10:31:02 JST 2026 # -a オプションで追記する $ date | tee -a time_log.txt Tue Apr 15 10:31:15 JST 2026 $ cat time_log.txt Tue Apr 15 10:31:02 JST 2026 Tue Apr 15 10:31:15 JST 2026
-a が必須です。付け忘れると前の記録が消えるので注意してください。複数のファイルに同時出力する
4. ファイルを複数指定する
tee はファイル名を複数指定できます。同じ内容を複数のファイルに同時に書き出せます。# 3つのファイルに同時に書き出す $ echo "server maintenance completed" | tee log1.txt log2.txt log3.txt server maintenance completed $ cat log1.txt server maintenance completed $ cat log2.txt server maintenance completed
sudo と tee の組み合わせ
5. root権限のファイルに書き込む
sudo でリダイレクトを使う場面は、Linuxの運用で頻繁に遭遇します。しかし、次のような書き方はうまくいきません。# これはエラーになる(リダイレクトは一般ユーザーのシェルが処理するため) $ sudo echo "nameserver 8.8.8.8" > /etc/resolv.conf bash: /etc/resolv.conf: Permission denied
> はシェルがリダイレクト処理を行うため、sudo の権限が及びません。sudo で実行されるのは echo だけで、ファイルへの書き込みは一般ユーザーの権限で実行されます。この問題を解決するのが
sudo tee です。# sudo tee でroot権限のファイルに書き込む $ echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf nameserver 8.8.8.8 # 画面出力が不要な場合は /dev/null にリダイレクトする $ echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf > /dev/null
tee が sudo の権限で動くため、root所有のファイルにも書き込めます。6. 追記する場合は sudo tee -a を使う
既存の設定を消さずに追記したい場合は-a を組み合わせます。# /etc/hosts に1行追加する(既存の内容は残す) $ echo "192.168.1.100 app-server" | sudo tee -a /etc/hosts > /dev/null # 追記されたことを確認する $ tail -1 /etc/hosts 192.168.1.100 app-server
パイプラインの途中でteeを使う
7. 中間結果をファイルに保存しながら処理を続ける
tee の真価は、パイプラインの途中に挟めることにあります。処理の中間結果をファイルに残しつつ、後続のコマンドにもデータを渡せます。# アクセスログから404エラーを抽出し、中間結果を保存しつつ件数を数える $ grep "404" /var/log/httpd/access_log | tee 404_errors.txt | wc -l 23 # 404エラーの詳細はファイルに残っている $ head -3 404_errors.txt 192.168.1.xxx - - [14/Apr/2026:10:23:45 +0900] "GET /old-page.html HTTP/1.1" 404 196 192.168.1.xxx - - [14/Apr/2026:10:24:12 +0900] "GET /deleted.css HTTP/1.1" 404 196 10.0.0.xxx - - [14/Apr/2026:10:25:01 +0900] "GET /api/v1/missing HTTP/1.1" 404 196
tee の価値が増します。8. 複数のteeを連結して段階的に保存する
tee はパイプライン内に何度でも配置できます。各段階の結果をそれぞれ別のファイルに残せます。# ステップ1: 全ログ → ステップ2: エラーだけ抽出 → ステップ3: IPアドレスだけ抽出 $ cat /var/log/httpd/access_log | tee all_log.txt | grep "500" | tee 500_errors.txt | awk '{print $1}' | sort -u 10.0.0.xxx 192.168.1.xxx
シェルスクリプトでのtee活用パターン
9. スクリプトの実行ログを画面とファイルの両方に出力する
シェルスクリプトの中でtee を使えば、実行経過を画面で確認しつつログファイルにも自動で残せます。#!/bin/bash # deploy.sh - デプロイスクリプトの実行例 LOG="/var/log/deploy_$(date +%Y%m%d_%H%M%S).log" echo "=== デプロイ開始: $(date) ===" | tee "$LOG" echo "ファイルを同期中..." | tee -a "$LOG" rsync -avz /app/release/ /var/www/html/ 2>&1 | tee -a "$LOG" echo "=== デプロイ完了: $(date) ===" | tee -a "$LOG"
tee だけ -a なし(ログファイルを新規作成)、2回目以降は -a 付き(追記)にすることです。10. 標準エラー出力もteeに渡す
デフォルトでは、tee は標準出力(stdout)だけを受け取ります。標準エラー出力(stderr)もまとめてファイルに保存したい場合は、2>&1 でリダイレクトしてからパイプに渡します。# 標準出力と標準エラー出力の両方をteeに渡す $ make 2>&1 | tee build.log # コマンドが成功してもエラーが出ても、すべてbuild.logに記録される
teeの注意点とトラブル対処
「Permission denied」が出た時の対処法
tee で書き込み先のファイルに権限がない場合、Permission denied が発生します。# 一般ユーザーでroot所有のファイルに書き込もうとした場合 $ echo "test" | tee /etc/test.conf tee: /etc/test.conf: Permission denied test # 解決策: sudo tee を使う $ echo "test" | sudo tee /etc/test.conf > /dev/null
teeの上書きに注意する
-a を付け忘れると、既存ファイルの内容が消えます。特にシェルスクリプトでループ処理中に tee を使う場合は、ループの初回だけ上書き、2回目以降は追記にするのか、全回追記にするのかを意識してください。バッファリングの影響
パイプライン内でtee を使うと、前段のコマンドの出力がバッファリングされて表示が遅れることがあります。リアルタイム性が必要な場合は、前段のコマンドに --line-buffered(grepの場合)や stdbuf -oL を付けます。# grepの出力がバッファリングされる問題を解消する $ tail -f /var/log/messages | grep --line-buffered "error" | tee error_realtime.log # stdbufを使う方法(grep以外のコマンドにも適用できる) $ tail -f /var/log/messages | stdbuf -oL grep "error" | tee error_realtime.log
本記事のまとめ
tee コマンドは、「画面で確認しながらファイルにも記録する」というサーバー運用の基本動作を1コマンドで実現します。| やりたいこと | コマンド |
|---|---|
| 画面とファイルに同時出力 | コマンド | tee ファイル名 |
| ファイルに追記 | コマンド | tee -a ファイル名 |
| 複数ファイルに同時出力 | コマンド | tee file1 file2 file3 |
| root権限のファイルに書き込み | echo "内容" | sudo tee /etc/ファイル名 |
| root権限のファイルに追記 | echo "内容" | sudo tee -a /etc/ファイル名 |
| 画面出力を抑えてファイルだけに書く | コマンド | tee ファイル名 > /dev/null |
| パイプの途中で中間結果を保存 | cmd1 | tee 中間.txt | cmd2 |
| stderrも含めてファイルに保存 | コマンド 2>&1 | tee ファイル名 |
tee は単体で使うだけでなく、パイプラインの途中に挟むことで真価を発揮します。ログ調査・デプロイ作業・障害対応のいずれでも、「画面で確認+ファイルに記録」を習慣にしておくと、あとから振り返るときに必ず役立ちます。
関連記事:
・リダイレクトの使い方|>・>>・<・2>&1・/dev/nullの全パターン実践例
・xargsコマンドで標準入力からコマンドを一括実行する方法|findとの組み合わせや並列処理も
teeの基本はわかった。次はサーバー構築全体の流れを押さえませんか?
tee はサーバー運用のほんの一部にすぎません。安全なサーバー構築を体系的に学ぶことが、現場で信頼されるエンジニアへの近道です。
ネットの切れ端の情報をコピペするだけでなく、現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
登録10秒/合わなければ解除3秒 / 詳細はこちら
