「LinuxLinux [リナックス / ライナックス]オープンソースのOSカーネルのコマンドを実行した結果を画面でリアルタイムに確認したいけれど、同時にログファイルとしても保存しておきたい」と思ったことはありませんか。通常のリダイレクト(> や >>)を使うと、出力結果がファイルにのみ保存されて画面には何も表示されなくなってしまい、進捗状況の確認に困っている方も多いでしょう。
この記事を読むと、linux tee コマンドの基本的な使い方から、標準出力を画面に表示しつつファイルへ保存する方法、さらに実務で役立つ追記オプションやパーミッションエラーを防ぐ正しいsudoの組み合わせ方まで理解できるようになります。
確認した環境
本記事で解説するコマンドは、以下の環境で動作を確認しています。
- OSOS [オーエス]Operating System。基本ソフトウェア: UbuntuUbuntu [ウブントゥ]人気のLinuxディストリビューション 24.04 LTS / AlmaLinux 9.4
- シェル: Bash / Zsh
Linuxのteeコマンドとは?標準出力を画面とファイルに分岐する仕組み
teeコマンドの役割と名前(T字継手)の由来
teeコマンドは、標準入力を受け取り、それを標準出力(画面)と1つ以上のファイルの両方に同時に書き出すためのコマンドです。
名前の由来は、配管工事で使用されるT字型の継手(Tee)からきています。水道管の流体を2方向に分岐させるように、Linuxのコマンドライン(CLICLI [シーエルアイ]Command Line Interface。コマンドで操作するインターフェース)においてデータの流れを「画面」と「ファイル」の2方向に分岐させます。
[コマンド] ---> (標準出力) ---> [ tee ] ---+---> (画面への出力) | +---> [ファイルへ保存]通常のリダイレクト(> や >>)との違いと使い分け
Linuxにおける一般的なリダイレクト(> や >>)は、標準出力をファイルに保存するため、通常は画面に何も表示されなくなります。そのため、処理が正常に進行しているかをリアルタイムで確認できません(※標準エラー出力は別途リダイレクトしない限り画面に表示されます)。
一方、teeコマンドは画面に結果を表示(標準出力)しながらファイルにも書き込みを行うため、両方のメリットを同時に得ることができます。
teeコマンドの基本的な使い方と構文
tee コマンド本来の書式は以下の通りです。
tee [オプション] [ファイル名...]実務では、他のコマンドからパイプ(|)経由で標準入力を受け取って使用することがほとんどです。
command | tee [オプション] <ファイル名>echoコマンドの標準出力をファイルに書き込む基本例
もっともシンプルな使い方は、何らかのテキストをパイプ経由で渡す方法です。
echo "Hello, Linux Tee Command" | tee output.txt実行時の出力例:
Hello, Linux Tee Commandこのコマンドを実行すると、画面に「Hello, Linux Tee Command」と表示されると同時に、カレントディレクトリに output.txt というファイルが作成され、その中にも同じ文字列が書き込まれます。
パイプ(|)と組み合わせてコマンド実行結果をログ保存する
実務では、システム情報の確認コマンドやビルドコマンドと組み合わせて使用されます。例えば、システムのディスク使用量を調べる df コマンドの結果を画面に表示しつつ、ログファイルとして保存する場合は以下のように記述します。
df -h | tee disk_usage.logこれにより、ディスクの使用状況を画面で確認しながら、後から参照するためのログファイルにも保存できます。
[!NOTE] 保存先の空き容量不足やアクセス権限エラーなどが発生した場合は、当然ながらログの書き込みに失敗します。また、入力元のコマンドが出力をバッファリングしている場合は、画面への表示やログ保存のタイミングが遅れることがあります。
標準エラー出力(エラーメッセージ)も同時にファイル保存する方法(2>&1)
通常のパイプ(|)は標準出力(stdout)のみを次のコマンドに渡します。そのため、コマンド実行時にエラーが発生した場合、エラーメッセージ(標準エラー出力 / stderr)は tee を経由せず画面に直接出力され、ファイルには保存されません。
エラーメッセージも含めてすべての実行結果をログに残したい場合は、標準エラー出力を標準出力にリダイレクト(統合)してから tee に渡します。
# POSIXシェルやBashで使える標準的な書き方(スクリプト移植性が高くおすすめ)command 2>&1 | tee app.log
# Bash 4.0以降やZshで利用できる短縮記法(|&)command |& tee app.logこの記法を使うことで、「ログファイルを確認したら肝心のエラー原因が記録されていなかった」というトラブルを防ぐことができます。なお、シェルによって短縮記法 |& の対応状況が異なるため、スクリプトの移植性を重視する場面では 2>&1 | を使うのが安全です。
実務で役立つteeコマンドの主要オプション
tee コマンドには、実務の現場で頻繁に利用されるいくつかの重要なオプションが用意されています。
既存ファイルに追記する(-a / —append オプション)
デフォルトの tee コマンドは、指定したファイルがすでに存在する場合、既存の内容を上書きします。過去のログを残したい場合や、複数回の実行結果を1つのファイルに蓄積したい場合は -a(--append)オプションを使用します。
echo "追加のログメッセージ" | tee -a app.logこのオプションを使用することで、ファイルがすでにある場合は末尾に新しいデータが追加(追記)されます。ファイルが存在しない場合は新規作成されます。
複数のファイルへ同時に出力・保存する
tee コマンドは、スペース区切りで複数のファイルを指定することで、1回のコマンド実行で同一のデータを複数のファイルに同時に書き込むことができます。
# 同一のログを通常ログ用とバックアップ用ファイルに同時保存する例uptime | tee current_load.log backup_load.log※この例は、同じ実行結果を複数の保管先へ同時に保存するものです(異なるサーバーの負荷を取得するわけではありません)。同じログデータをリアルタイム監視用と長期保管用へ同時に振り分けたい場合などに役立ちます。
割り込みシグナル(SIGINT)を無視する(-i オプション)
-i(--ignore-interrupts)オプションを指定すると、tee が割り込みシグナル(SIGINT)を無視するようになります。
long_running_command | tee -i process.logただし、このオプションは tee 自身が SIGINT を無視するためのもの であり、パイプライン全体の処理継続やログの完全な保存を保証するものではありません。例えば Ctrl + C を押した際に入力元の long_running_command 側が終了してしまえば、tee への入力も途切れるため、ログは途中までしか保存されません。
不用意な割り込みで tee 側のパイプ処理が即座に落ちるのを防ぎたい場面で活用されます。
sudoとteeコマンドを組み合わせて管理者権限でファイル保存する方法
システムの設定ファイル(例: /etc/hosts や /etc/fstab など)を変更する際、管理者権限が必要になるため sudo を使ってリダイレクトしようとしてつまずく初心者が多くいます。
よくある失敗:sudoとリダイレクト(>>)で「Permission denied」になる理由
以下のようなコマンドを実行したことはないでしょうか。
# 失敗する例sudo echo "192.168.1.50 myserver" >> /etc/hostsこのコマンドを実行すると、以下のようなパーミッションエラーが発生して書き込めないことがあります。
-bash: /etc/hosts: 許可されていない操作です (Permission denied)原因:
sudo が適用されているのは echo コマンドの部分のみであり、リダイレクト(>>)を実行しているシェル自体は一般ユーザー権限のまま動作しているためです。
sudo teeで管理者権限のファイルに追記・書き込みする正しい手順
管理者権限でファイルに書き込みを行いたい場合は、sudo と tee コマンドを組み合わせて以下のように記述します。
echo "192.168.1.50 myserver" | sudo tee -a /etc/hostsこの仕組みのポイント:
echoコマンドは一般ユーザー権限で文字列を出力する。- パイプラインを経由して渡されたデータを、
sudo teeが管理者権限で保護されたファイル(/etc/hosts)に対して書き込む。
画面への不要な出力を抑えたい場合は、tee の標準出力を /dev/null に捨てるとすっきりと実行できます。
echo "192.168.1.50 myserver" | sudo tee -a /etc/hosts > /dev/null【Tips】シェルスクリプトで使う場合の終了ステータス(Exit Code)の注意点
シェルスクリプト内で command | tee output.log を実行し、直後に $? でコマンドの成否を判定しようとする場合、注意が必要です。
パイプライン全体の終了ステータス($?)は、最後に実行されたコマンド(この場合は tee)の終了ステータス(通常は 0)になってしまいます。そのため、前の command が失敗していてもスクリプトが「成功」と誤認してしまうケースがあります。
各シェルでコマンドのエラーを正しく検知したい場合は、以下の方法を使い分けます。
方法1:各コマンドの終了ステータスを変数に退避して確認する
Bash環境では、PIPESTATUS 配列を使ってパイプライン内の各コマンドの終了ステータスを取得できます。PIPESTATUS[0] は command、PIPESTATUS[1] は tee の終了ステータスです。
後続のコマンドを実行すると PIPESTATUS の値は上書きされてしまうため、パイプライン実行直後に変数へ退避するのが確実です。
# Bashの場合(PIPESTATUS配列を使用)command | tee output.logstatus=${PIPESTATUS[0]}
echo "commandの終了ステータス: $status"※ Zshの場合は、同様の情報を小文字の pipestatus 配列(status=${pipestatus[1]} ※Zshは1始まり)で取得できます。
方法2:パイプライン内の失敗を検知する(set -o pipefail)
スクリプト冒頭で set -o pipefail を宣言しておくと、パイプライン内のいずれかのコマンドが失敗した場合、パイプライン全体の終了ステータス($?)が「最後に失敗したコマンドの終了ステータス」になります。
# スクリプト冒頭に記述しておくことで、commandの失敗を$?で検知可能set -o pipefail
command | tee output.logif [ $? -ne 0 ]; then echo "エラーが発生しました"fiset -o pipefail: パイプライン途中の失敗を検知してスクリプトを安全に停止・分岐させたい場合に有効。PIPESTATUS/pipestatus: コマンドごとの終了ステータスを個別に詳細ログ出力・判定したい場合に有効。
まとめ:teeコマンドを使いこなしてログ記録を効率化しよう
本記事では、Linuxの tee コマンドの基本的な仕組みから実用的な使い方まで解説しました。記事のポイントを以下にまとめます。
teeコマンドは、標準入力を受け取り、画面(標準出力)とファイルの両方に同時に出力する。- 通常のリダイレクト(
>)と異なり、実行結果を画面で確認しながらログを保存できる。 - エラー出力(標準エラー出力)もログに残したい場合は
2>&1 | tee(または対応シェルで|& tee)を使用する。 - 既存ファイルを上書きせずに追加で保存したい場合は
-a(--append)オプションを使用する。 - 複数のファイルをスペース区切りで指定すれば、同一データを複数ファイルへ同時に出力が可能である。
- 管理者権限が必要なファイルへの書き込みには、
sudo teeを組み合わせるのが効果的である。 - スクリプトでエラー判定を行う場合は、Bashの
PIPESTATUS(Zshはpipestatus)やset -o pipefailを活用する。
tee コマンドを活用することで、日々の運用管理やスクリプト作成におけるログ収集作業が効率的になります。ぜひ日々のコマンドライン操作に取り入れてみてください。
以上で本記事の解説を終わります。
よいITライフを!
人気記事
- 1
- 2
- 3
- 4
- 5
Rocky Linux対応。実際にWebサーバーを公開するまでのプロセスを体験できる、最も確実で実践的なガイドブックです。