たまに、標準出力も標準エラー出力もログに記録しつつ、画面に標準エラー出力を出したいとかのケースで、標準出力を2つのストリームに複製して別の処理をさせたいなぁって時があります。
tee 単体で出来るじゃん!
こんな感じ。
seq 10 | tee >(cat > all.log) >(grep '[02468]$' > even.log) >(grep '[13579]$' > odd.log)
これでよかった。
古い内容(今となっては若気の至りな内容…だがまぁこねくりまわしてみたかった黒歴史として残しておく)
そんな時は tee /dev/stderr
すると便利な時があるよってメモです。
例
上記リンク先のケースに当てはめてみると↓こんな感じで書けます。
## 上書き
command >/tmp/foolog 2> >(tee /dev/stderr)
## 追記
command >>/tmp/barlog 2> >(tee /dev/stderr)
説明
データの流れは以下の図のような感じになってます。
command ─┬─ 1 ──────────────┬─────────> /tmp/foolog
└─ 2 ─> tee ─┬─ 1 ─┘
└─ /dev/stderr ─> 2
- commandの標準エラーをteeに繋げて、
- teeの引数にstderrを指定することで1本の標準入力を標準出力と標準エラーに複製してます。
- で、teeの標準出力はcommandの標準出力に合流して合体、
- stderrから生まれた標準エラーはそのまま外部に垂れ流されてttyに表示されたりcronにキャッチされたりする感じです。
> >(...)
の部分はBashの Process Substitution っていう機能で、以前書いたエントリの「2つのコマンドの出力結果のdiffを取る」とか「teeでgz圧縮しながら保存させる」とかでも使ってます。上手く使うと中間ファイルが必要そうなところが不要になって結構便利です。