观察/阅读不断增长的日志文件

时间:2009-08-18 13:04:45

标签: ruby logging io

我有一个不断增长的日志文件。如何通过Ruby脚本观察和解析它?

当新行包含字符串'ERROR'

时,脚本将在写入文件时解析每个新行并输出一些内容。

7 个答案:

答案 0 :(得分:17)

def watch_for(file, pattern)
  f = File.open(file,"r")
  f.seek(0,IO::SEEK_END)
  while true do
    select([f])
    line = f.gets
    puts "Found it! #{line}" if line=~pattern
  end
end

watch_for("g.txt",/ERROR/)

感谢ezpz的想法,使用select方法可以得到你想要的东西。 select方法正在监听IO的流,读取“迟到”的字节。

答案 1 :(得分:8)

您可以通过以下方式使用Kernel#select

def watch_for(file,pattern)
   f = File.open(file,"r")

   # Since this file exists and is growing, seek to the end of the most recent entry
   f.seek(0,IO::SEEK_END)

   while true
      select([f])
      puts "Found it!" if f.gets =~ pattern
   end
end

然后称之为:

watch_for("some_file", /ERROR/)

我已经省略了所有的错误检查等等 - 你会想要这个以及可能有一些机制来摆脱循环。但基本的想法就在那里。

答案 2 :(得分:5)

如果你在Linux上......

tail -f log/development.log | grep "ERROR"

除非你真的希望它出于某种原因成为Ruby脚本。

答案 3 :(得分:5)

有两种方法:

  • 在无限循环中轮询文件(就像在钱ig贵的回答中一样,但最好将一些sleep置于无限循环中)
  • 使用OS事件子系统:BSD上的kqueue,Linux上的inotify

这是我写的一篇文章:Ruby for Admins: Reading Growing Files。因此,结合事件子系统和轮询的程序如下所示:

def tail_dash_f(filename)
  open(ARGV.first) do |file|
    file.read          
    case RUBY_PLATFORM   # string with OS name, like "amd64-freebsd8"
    when /bsd/, /darwin/
      require 'rb-kqueue'
      queue = KQueue::Queue.new     
      queue.watch_file(ARGV.first, :extend) do
        yield file.read             
      end
      queue.run                     
    when /linux/
      require 'rb-inotify'
      queue = INotify::Notifier.new  
      queue.watch(ARGV.first, :modify) do
        yield file.read             
      end
      queue.run                      
    else
      loop do           
        changes = file.read
        unless changes.empty?  
          yield changes
        end
        sleep 1.0       
      end
    end
  end
end

tail_dash_f ARGV.first do |data|
  print data
  if data =~ /error/i
    # do something else, for example send an email to administrator
  end
end

答案 4 :(得分:3)

查看file-tail gem

答案 5 :(得分:3)

穷人的快速做法:

  1. 执行

    的Ruby脚本
    ARGF.each do |line|
      ...
    
  2. 运行屏幕:

    tail -f file | ruby script 
    

答案 6 :(得分:2)

研究@Qianjigui的想法但不使用100%CPU:

def watch_for(file, pattern)
  # Replace -n0 with -n+1 if you want to read from the beginning of file
  f = IO.popen(%W[tail -f -n0 #{file}])
  loop do
    select([f])
    while line = f.gets
      puts "Found it! #{line}" if line =~ pattern
    end
  end
end

watch_for('g.txt', /ERROR/)