Goでファイルの特定位置から読む
bashで組んでたログの検知スクリプトを、メンテナンス性と拡張性考えてGoで書き直すことにしました。 ファイルを定期的にtailして一定行数読み込んで処理する方式を取っていましたが、最後に読んだとこから後にしたいと調べていたら、Mackerelが似たようなことをやっていたので参考にしました。
go-check-plugins/check-log.go at master · mackerelio/go-check-plugins · GitHub
File.Seek()を使って、ファイルの特定バイトから読むようにできます。 前回読み込んだバイト数を記録しておけば、次はその後から追加されたデータのみを読むことができます。
whence*1が、ぱっと見何かわからなかったのですが、この値によってoffsetの使われ方が変わります。
whence | 意味 |
---|---|
0 | ファイルの先頭からのoffset(先頭からスキップするバイト数) |
1 | 今のSeek位置からのoffset(前回Seekした位置からスキップするバイト数) |
2 | ファイルの末尾からのoffset(末尾から読む。この場合は負数にしないと読めません) |
サンプル
一部抜粋
data
File seek in Go.
コード
fp, err := os.Open("./data") if err != nil { panic(err) } defer fp.Close() fp.Seek(5, 0) b, err := ioutil.ReadAll(fp) if err != nil { panic(err) } fmt.Printf("offset 5, whence 0: %s\n", string(b))
出力
offset 5, whence 0: seek in Go.
whence=2の時にoffsetをマイナスにしてなくて、読めないなーと勘違いしてました。今回試したのはReadですがWriteも同様に位置指定して書き込めるようです。その際は、os.Open()はReadOnlyなので、os.OpenFile(), os.Create()あたりで書き込める状態で作る必要があります。