こんにちは、Reoです。
現在はフリーランスのインフラエンジニアとして働きながら、インフラ特化の学習サービス「InfraDojo(インフラ道場)」を運営しています。
Linuxでコマンドを実行したとき、
「結果を画面で確認しながら、ファイルにも残したい」
と思ったことはありませんか?
そんなときに使えるのが、teeコマンドです。
今回は、練習用のログを使って、画面への表示とファイルへの保存、上書きと追記の違いを確認します。
1. teeは、受け取ったデータを2方向へ出力する
teeは、標準入力から受け取ったデータを、標準出力と指定したファイルの両方へ書き出すコマンドです。GNU Coreutils公式ドキュメント:tee
最初は、次の流れで考えてみてください。
コマンドの出力
↓
tee
├── 画面に表示
└── ファイルに保存
この記事のように、teeの後ろに別のパイプや出力先の指定がなければ、標準出力は通常ターミナル画面へ表示されます。
例えば、次のように使います。
grep "ERROR" practice.log | tee errors.log
これは、次の処理をつないだものです。
-
practice.logから、ERRORを含む行を探す - 検索結果を
teeへ渡す - 結果を画面へ表示し、
errors.logにも保存する
|は「パイプ」と呼ばれ、左側のコマンドの標準出力を、右側のコマンドの標準入力へ渡します。
実際に試していきましょう。
2. 練習用のログファイルを準備する
Bashが使えるLinux環境を想定しています。管理者権限は不要です。
まず、練習用の一時ディレクトリを作り、そこへ移動します。
practice_dir=$(mktemp -d) && cd "$practice_dir"
mktemp -dは、名前が重ならない一時ディレクトリを作るコマンドです。
エラーが出ていなければ、以降も同じターミナルで操作してください。
次に、3行の練習用ログを作成します。
printf '%s\n' \
'INFO service started' \
'ERROR connection failed' \
'INFO retry scheduled' > practice.log
printfで表示した文字列を、>でpractice.logへ保存しています。これは練習用の架空のログです。
内容を確認します。
cat practice.log
出力:
INFO service started
ERROR connection failed
INFO retry scheduled
3. 検索結果を表示しながら保存する
準備したファイルから、ERRORを含む行を検索します。
grep "ERROR" practice.log | tee errors.log
画面には、次の1行が表示されます。
ERROR connection failed
続いて、保存先のファイルを確認しましょう。
cat errors.log
出力:
ERROR connection failed
画面で確認したものと同じ内容が、ファイルにも保存されています。
ここで、次の2つを比べてみます。
grep "ERROR" practice.log > errors.log
grep "ERROR" practice.log | tee errors.log
| 書き方 | 検索結果を画面に表示 | ファイルに保存 |
|---|---|---|
> errors.log |
しない | する |
| tee errors.log |
する | する |
この表は、検索結果として出力される標準出力についての比較です。
画面でも確認しつつ、あとから読み返せるように残したいときに、teeが使えます。
4. tee -aで、既存の内容に追記する
次に、別のメッセージを追加してみます。
既存の内容を残して末尾に追加するときは、-aを付けます。
printf '%s\n' 'ERROR retry failed' | tee -a errors.log
画面の出力:
ERROR retry failed
保存された内容を確認します。
cat errors.log
出力:
ERROR connection failed
ERROR retry failed
最初に保存した行が残り、その下へ新しい行が追加されました。
画面に表示されるのは、今回teeへ渡したデータです。
-aを付けても、保存先にある過去の内容をまとめて画面に表示するわけではありません。ファイル全体を見るときは、今回のようにcatなどを使います。
5. -aを付けない場合は上書きになる
今度は、-aを付けずに実行してみましょう。
printf '%s\n' 'ERROR new check failed' | tee errors.log
画面の出力:
ERROR new check failed
ファイルを確認します。
cat errors.log
出力:
ERROR new check failed
先ほどまでの2行は残らず、今回の内容に置き換わっています。
teeは、保存先が存在しなければファイルを作成します。すでに存在する場合は、通常は上書きし、-aを付けると追記します。GNU Coreutils公式ドキュメント:上書きと追記
使う前に、どちらの目的なのかを決めておきましょう。
| 目的 | 書き方 |
|---|---|
| 今回の結果でファイルを作り直す | tee ファイル名 |
| 以前の結果を残して追加する | tee -a ファイル名 |
また、tee -aは重複を取り除く機能ではありません。同じデータを繰り返し渡せば、その回数だけ追記されます。
6. 「画面に出たものが全部保存される」とは限らない
ここで、ひとつ区別しておきたいことがあります。
通常の|が渡すのは、左側のコマンドの標準出力です。
コマンド自身のエラーメッセージなどに使われる標準エラー出力は、そのままではteeへ渡りません。
今回のログには、次の文字が含まれていました。
ERROR connection failed
これは、練習用ファイルに書いた文字列です。grepが検索結果として表示するので、標準出力としてteeへ渡ります。
一方、読み込むファイルが存在しない場合にgrep自身が出すエラーメッセージは、標準エラー出力です。
文字列にERRORと書かれているかどうかで、出力先が決まるわけではありません。
まずは、「検索で見つけたログの行」と「検索コマンド自身のエラー」を分けて考えてみてください。
7. 読み込むファイルと保存先は、別の名前にする
今回の例では、次のようにファイルを分けています。
読み込み元:practice.log
保存先 :errors.log
このように、入力と出力には別のファイルを指定してください。
同じファイルを読みながら、そのファイルへteeで上書きすると、読み込みが終わる前に内容が消されるなど、期待どおりに処理できない可能性があります。
練習するときも、
元のデータを読む → 加工する → 別のファイルへ保存する
という流れにすると、処理前後の内容を確認しやすくなります。
Linuxの操作を、結果まで確認する練習にしたい人へ
今回は、コマンドを実行したあとに、保存先のファイルも読み返しました。
画面に表示された。
ファイルにも保存されていた。
追記したら増え、上書きしたら置き換わった。
このように、入力したコマンドと、実際に起きた変化を結び付けることが大切です。
自分が運営するInfraDojo(インフラ道場)でも、課題を読み、コマンドを入力し、結果を確認しながら学習できます。
▼ InfraDojo(インフラ道場)
InfraDojoは、ブラウザ上のターミナルでLinuxコマンドを実際に入力しながら学べる、インフラエンジニア向けの実践学習プラットフォームです。環境構築不要・無料で始められます。
演習は学習用シミュレーター上で行い、無料の入門コースから取り組めます。