Created
June 4, 2013 21:24
-
-
Save mikeda/5709726 to your computer and use it in GitHub Desktop.
ログの差分出力スクリプト
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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