App::Rolling - 標準入力を世代管理されたファイルに書き出す
前置き
こんにちは。bayashi です。みなさん、意識は高まっていますか? 僕は上々です。今回は拙作の App::Rolling というモジュールを紹介いたします。
といっても、絶賛開発中のモジュールなので、ここで紹介したインターフェースは変更されるかもしれません。
つまり、人柱、大歓迎で㌃
何をするモジュール?
App::Rolling は、標準入力を世代管理されたファイルに書き出す目的で作っています。例えば、いつ起きるかわからない適当な通信のTCPダンプを取得したい場合、ひとつのファイルにひたすら書き出して捉えるのは、なんとなく気が引けますよね。そんなとき、App::Rolling に同梱される roll コマンドを使えば、好きな間隔で、好きな世代だけローテートさせながら、ファイルに書き出すことができるようになります。
通常、以下のようにダンプとったりしますね。
$ /usr/sbin/tcpdump | tee > /tmp/dump.log
roll コマンドで、以下のようにすると、`dump.log.1230` `dump.log.1231` `dump.log.1232` `dump.log.1233` `dump.log.1234` というように、自動的にファイルが世代管理(デフォルト5世代)されて書き出されます。
$ /usr/sbin/tcpdump | roll -t /tmp/dump.log
だから、放置しても、安心★キラッ
オプション
次のようなオプションがあります。
-f --file 書き出すファイルを指定します *必須* -a --age ローテートする世代数 [デフォルト:5] -i --interval 1世代に書き出す時間(秒) [デフォルト:60] -t --through ファイルに書き出しつつ、標準出力にもアウトプットします -nr --no-rotate ローテートしません -h --help ヘルプを表示します -v --version バージョンを表示します
例えば以下のように書くと、10世代でローテーションして、1世代が180秒間の出力を確保します。あわせて、`-t` オプションで dump出力を STDIN に垂れ流して、リアルタイムで観察したりもできます。
$ /usr/sbin/tcpdump | roll -f /tmp/dump -a 10 -i 180 -t
内緒だけど、ファイル指定は -f で指定しなくてもいけるみたいよ♪
設定
オプションで指定する値は、規定のファイルに記述しておけば、毎度指定する必要がありません。
デフォルトでは `~/.rolling/config` が読まれます。$ENV{'ROLLING_DIR'} で任意のディレクトリの config ファイルを指定することも可能です。
config ファイルの中身は、例えば以下のようになります。
file: /tmp/roll.log age: 3 interval: 180 through: 1
既知のバグ
書いてはみたものの、以下のようなバグがあります 、、orz
- STDINにインターバルを超えて入力がない場合に、ローテートがうまくいかない
- ファイル存在チェックのせいでパフォーマンスが悪い
TODO
今後、実装予定の機能。
- インターバルで `-i 3m` (現状の書き方だと -i 180)とか書きたい
- ファイルサイズでローテーション
- 出力するファイルの先頭にタイムスタンプ
- grep オプション
他にもこんなの欲しい!というのがあったら教えてください!
コマンドラインツールの書き方
個人的に、コマンドラインツールを書くときは、ほとんどいつも同じコードをベースに書いています。もともとは Module::Starter あたりからコピペした気がしますが、興味のある人はソース覗いてみてください。Getopt::Long や Pod::Usage を使ってオプション値を取得したりヘルプを表示したりといった基本的なつくりや、設定ファイルの読み込みなどは鉄板化していますね。
ただ、コマンドラインツールはテストがけっこう大変になったりすることがあり、App::Cmd をベースにして、App::Cmd::Tester を使うのがいいかもと、App::Rolling を書いた後で気づいたりしました。
今後、この手のモジュールを書く人は、検討してみるといいと思います!
まとめ
App::Rolling というモジュールを紹介しました。関心を持っていただければ幸いです。