LoginSignup
54

More than 5 years have passed since last update.

標準出力に表示をしながらファイルにも保存して、かつローテーションもする

Last updated at Posted at 2016-02-07

Linux/Macなどのターミナル上での作業を想定しています。

「出力を表示しつつもファイルに書き出す」操作は、teeへパイプを結ぶことで実現できます。得られた出力を目視しつつ、ログファイルとして保存する時などに重宝します。

$ echo "hoge" | tee hoge.log
hoge
$ cat hoge.log # => hoge

書き出すファイルをローテートさせる

teeはとてもシンプルで便利なコマンドなのですが、要求が複雑になると対応が難しくなります。

  • 上の例でいうhoge.logが巨大になってしまう
  • いつ頃に出力されたのか日付入りのファイルに出力させたい

こんな時には、teeでは力不足になってしまいます。

そこで、ログローテートをしてくれるコマンドにパイプするようにします。例えば、rotatelogscronologがあります。

ここではrotatelogs1を使ってみました。-nオプション2と出力先ファイル、1つあたりのファイルサイズを指定すると、ファイルにsuffixを付けた上でローテートしてくれます。

# 3194880 = 3M (3 * 1024 * 1024)
$ yes hoge | head -c 3194880 | rotatelogs -n 3 /tmp/hoge.log 1M
$ wc -c /tmp/hoge*
 1064960 /tmp/hoge.log
 1064960 /tmp/hoge.log.1
 1064960 /tmp/hoge.log.2
 3194880 total

表示もさせたい

ファイル出力についてはいい感じになったのですが、rotatelogsは標準入力を吸い取ってしまうので、そのまま使うとteeのように表示と保存を両立させることができません。

解決法として単純なのは、rotatelogsには-eオプションがあるのでそれを使うことです。標準入力をそのまま標準出力に流してくれます。

$ echo "hoge" | rotatelogs -e -n 3 hoge.log 1M
hoge

別のアプローチとして、process substitutionを使う方法が考えられそうです。

$ echo "hoge" | tee >(rotatelogs -n 3 hoge.log 1M)
hoge
$ cat hoge.log
hoge

つまり、teeでターミナルに出力させつつ、ファイルの書き出し先を名前付きパイプにした上で、そちらにrotatelogsの標準入力をつなぎます。前述のcronologには-eのようなオプションがなさそうですし、こちらのほうがより汎用性が高そうに見えます。

まとめ

  • 標準出力を保存するときはteeが使える
  • 保存先にローテートなどの工夫をしたい時はrotatelogsなどを導入するとよさそう
  • process substitutionは色々と応用が利きそう

  1. だいぶ歴史があるらしいログローテート用のコマンドだけあって、多機能で便利です。ただ軽く実験した限り、ファイルサイズ上限が小さすぎるとローリングが間に合わない(?)こともあるようなので、厳密なファイル分割には向かないのかも? 

  2. ちなみに-nは比較的新しいバージョンでしか利用できません(2.4.5かららしいです)。 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
54