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

Kin*_*Ink 19 ruby io logging

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

该脚本将在写入文件时解析每个新行,并在新行包含字符串'ERROR'时将某些内容输出到屏幕

小智 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/)
Run Code Online (Sandbox Code Playgroud)

感谢ezpz的想法,使用select方法,你得到你想要的.select方法正在侦听IO的流,读取"迟到"的字节.

  • 注意:`select`总是在文件流上使用时立即返回:您始终可以从该文件流中读取EOF,因此您的ruby进程在等待文件更新时最终会旋转.不同的操作系统倾向于提供不同的工具来等待文件,Linux有inotify,而OS X有fsevents--也有方便的ruby gem包装它们. (4认同)
  • 这是*INCORRECT*实现,这里的选择不会阻止.它的工作原理是因为您读取的EOF无法进行比较. (3认同)

ezp*_*zpz 9

您可以通过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
Run Code Online (Sandbox Code Playgroud)

然后称之为:

watch_for("some_file", /ERROR/)
Run Code Online (Sandbox Code Playgroud)

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


Gry*_*ych 6

有两种方法:

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

这是我写的一篇文章:Ruby for Admins:阅读成长文件.因此,结合事件子系统和轮询的程序如下所示:

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
Run Code Online (Sandbox Code Playgroud)


cak*_*rus 5

如果你在Linux上...

tail -f log/development.log | grep "ERROR"
Run Code Online (Sandbox Code Playgroud)

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