2017年3月10日金曜日

Ruby で tail -f

概要

Ruby でログファイルを tail -f 的なことができないかなと思っていたら、ばっちりの gem があったので使ってみました

環境

  • Mac OS X 10.10.5
  • Ruby 2.2.0p0
  • Gem 2.4.5
  • file-tail 1.1.0

file-tail のインストール

  • gem install file-tail

サンプルコード

  • vim file_tail_sample.rb
require "file-tail"

filename = 'sample.log'

File.open(filename) do |log|
  log.extend(File::Tail)
  log.interval = 0
  log.backward(0)
  log.tail { |line| puts line }
end

実行

  • while :; do date >> sample.log; sleep 1; done;

ファイルに定期的に date の内容を出力します

  • ruby file_tail_sample.rb

でファイルに出力された情報が 1 行ずつ表示されると思います

Tips

メソッドについて

  • interval ・・・ 開始時に指定した秒数 wait します、10 を指定すると 10 秒 wait している間にファイルに書き込まれたファイルをバッファした後で出力を開始します
  • backward ・・・ 何行戻ってからファイル読み込みを開始するか指定します、20 を指定すると 20 行分前の情報を処理してから最新の書き込まれた行を処理します

その他詳しい内容なソースを読むかこのあたりを参考にしてください

ファイル名が変更された場合の挙動

サンプルで読み込んでいる sample.log を mv した場合は、新たに作成された sample.log の読み込みがちゃんと開始されました
ただ、mv 直後ではなく、mv 後に 10 秒くらいしてから新しいファイルへの処理が始まりました
もちろん 10 秒の間で書き込まれた情報はちゃんと出力されました

ただ、今回の場合は sample.log に対して while で sleep して date をリダイレクトしているので、一瞬 sample.log がどのプロセスからも掴まれていない状況が発生しています
ので、sample.log が別のプロセスにずっと掴まれている状態を作って、それで mv してみたところ file_tail_sample.rb の出力が止まってしまいました
確かに sample.log が作成されておらず、mv した先のファイルに対してログを出力し続けていました

ちなみにそのログを出力し続けるプログラムは以下の通り

require 'logger'

log = Logger.new("sample.log")

while true do
  now = DateTime.now
  log.debug(now.to_s)
  puts now
  sleep 1
end

のでログローテートが発生する環境などでは、ちゃんと file-tail しているファイルが一回どのプロセスからも掴まれなくなり、ちゃんと新規の対象ファイルが作成されるようにしてください(当たり前か)

0 件のコメント:

コメントを投稿