Skip to content

Instantly share code, notes, and snippets.

@mikeda
Created June 4, 2013 21:24
Show Gist options
  • Select an option

  • Save mikeda/5709726 to your computer and use it in GitHub Desktop.

Select an option

Save mikeda/5709726 to your computer and use it in GitHub Desktop.
ログの差分出力スクリプト
#!/usr/local/bin/ruby
# ログの差分出力スクリプト
# 使用例
# 前回実行からの追記分を出力する
# $ logtail.rb access_log
#
# ログのローテートに対応させる場合はオプションでローテートファイルを指定する
# $ logtail.rb access_log -r access_log.1
#
# デフォルトでは/tmp/<ログファイル名>.logtail.offsetに前回出力情報が保存される。
# 日付つきファイルなどファイル名が変わる場合、
# 同じファイルを複数バッチから処理する場合はこのファイルパスを個別に指定すること
# $ logtail.rb access_log.20130602 -r access_log.20130601 -o /tmp/test_access_log.logtail.offset
#
# TODO:オフセットファイルの作成、書き込み権限のチェック
require 'optparse'
require 'pp'
options = {}
OptionParser.new do |opt|
opt.on('-r', '--rotated_log=VAL') {|v| options[:rotated_log] = v}
opt.on('-o', '--offset_file=VAL') {|v| options[:offset_file] = v}
opt.parse!
end
log = ARGV.shift
exit 1 unless log
class LogTail
def initialize(log, options)
@log = log
@rotated_log = options[:rotated_log]
@offset_file = options[:offset_file] || "/tmp/#{File.basename(log)}.logtail.offset"
@offset = load_offset
end
def load_offset
return nil unless File.exist? @offset_file
line = File.read(@offset_file)
ino, pos = line.split(',')
{ ino: ino.to_i, pos: pos.to_i}
end
def save_offset(ino, pos)
File.write(@offset_file, "#{ino},#{pos}")
end
def tail_print(log, pos)
file = File.open(log)
file.seek(pos)
file.each{|line| puts line}
end_pos = file.pos
file.close
return end_pos
end
def tail_rotated_log
return unless @offset && @rotated_log && File.exists?(@rotated_log)
stat = File.stat(@rotated_log)
if @offset[:ino] == stat.ino && @offset[:pos] < stat.size
end_pos = tail_print(@rotated_log, @offset[:pos])
save_offset(stat.ino, end_pos)
end
end
def tail_log
return unless @log && File.exists?(@log)
stat = File.stat(@log)
if @offset && @offset[:ino] == stat.ino
if @offset[:pos] < stat.size
start_pos = @offset[:pos]
elsif @offset[:pos] < stat.size
save_offset(stat.ino, end_pos)
return
else
return
end
else
start_pos = 0
end
end_pos = tail_print(@log, start_pos)
save_offset(stat.ino, end_pos)
end
def execute
tail_rotated_log
tail_log
end
end
LogTail.new(log, options).execute
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment