はじめに
スクリプトやコマンドの実行結果をログファイルに残しつつ、標準出力でリアルタイムで確認したい場合があります。そんな時に便利なのがtee
コマンドです。
今回はtee
コマンドの応用として、エラーハンドリングを考慮した応用的な使い方を紹介します。
結論を読みたい方は👇🏼こちら
teeコマンドの基本的な使い方
command | tee result.log
command
の実行結果が標準出力に表示されると同時に、result.log
にも保存されます。
エラー出力もログに含める
基本的な使い方では標準出力のみがログに記録されますが、エラー出力も含めたい場合は、2>&1
を使用します。
command 2>&1 | tee result.log
exit codeの伝播
パイプライン処理では、デフォルトで最後のコマンドの終了コードのみが返されます。
つまり、command
が失敗してもtee
が成功すれば、パイプライン全体は成功として扱われてしまうのです。
これを防ぐにはset -o pipefail
を使用します:
set -o pipefail; command 2>&1 | tee result.log
pipefail
を設定することで、パイプラインの中で最後に失敗したコマンドの終了コードが返されるようになります。
検証してみる
# パイプラインで終了コードをセットする
$ ( set -o pipefail; exit 1 | exit 2 | exit 3 | cat )
# 直前の終了コードを出力
$ echo $?
# 最後に失敗したコマンドの終了コードが返される
3
コメントでわかりやすい検証コードを頂きました。ありがとうございます!
あとがき
最近ではリッチなターミナルアプリも流行ってきており、exit codeを検出してくれる物もありますよね。この方法はそういったターミナルにもよくマッチすると思います。
と言うのも、私はWarpと言うターミナルアプリを最近使い始めたり、シェルスクリプトをちゃんと学び始めたりして、この方法に辿り着きました。
シェルスクリプトでは直接ログを書くことが多いので標準出力に出す機会は少ないとは思いますが、一応この方法はシェルスクリプト内でも動きます。
シェルスクリプトの場合はワンライナーにしなくて良いので、最初の方の行にset -o pipefail
を書くと良いですね。