概要
こんなやり方あるって知らなかったので、目からウロコでした。
忘れないうちにメモメモ。。。
何かの出力を標準出力と標準エラー出力に分けてリダイレクトさせるのは以下で出来ます。
$ ./script.sh 1> stdout.log 2> stderr.log
このパターン、とても便利でよく利用しますが、ターミナルに情報は表示されなくなってしまいます。
リダイレクトしているので当たり前です。でも、見たいときがあります。
そのようなときは、以下のように bash の プロセス置換 (process substitution) と tee コマンドをあわせ技で使います。
$ ./script.sh 1> >(tee -a stdout.log) 2> >(tee -a stderr.log >&2)
こうやると、ファイルに出力しつつ、teeコマンドによってターミナルにも出力されます。素晴らしい。
サンプル
以下のようなスクリプトがあるとします。データ出力用です。
#!/usr/bin/env bash set -ue -o pipefail export LC_ALL=C echo 'stdout' echo 'stderr' 1>&2
んで、以下のような実行スクリプトがあるとします。
#!/usr/bin/env bash # https://moneyforward.com/engineers_blog/2015/05/21/bash-script-tips/ set -ue -o pipefail export LC_ALL=C # https://stackoverflow.com/questions/692000/how-do-i-write-stderr-to-a-file-while-using-tee-with-a-pipe sh ./script.sh 1> >(tee -a stdout.log) 2> >(tee -a stderr.log >&2)
後は、一応Makefile。
run: @chmod +x ./main.sh @./main.sh confirm: @echo '--- STDOUT ---' @cat ./stdout.log @echo '--- STDERR ---' @cat ./stderr.log clean: rm -f ./std*.log
んで、実行してみると
$ make run ; make confirm ; make clean stdout stderr --- STDOUT --- stdout --- STDERR --- stderr rm -f ./std*.log
ちゃんとターミナルに出力しつつ、ファイルにも書き込めています。
参考情報
linux - How do I write stderr to a file while using "tee" with a pipe? - Stack Overflow
bash: 標準出力、標準エラー出力をファイル、画面それぞれに出力する方法 - Qiita
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。