Подтвердить что ты не робот

Смотреть/читать растущий файл журнала

У меня есть файл журнала, который постоянно растет. Как я могу смотреть и анализировать его с помощью Ruby script?

script будет анализировать каждую новую строку, поскольку она записывается в файл и выводит что-то на экран, когда новая строка содержит строку "ERROR"

4b9b3361

Ответ 1

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 прослушивает поток ввода-вывода, читает байты, что приходит "поздно".

Ответ 2

Вы можете использовать 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/)

Я отклонил все проверки ошибок и т.д. - вы захотите, чтобы это и, вероятно, какой-то механизм вырвался из цикла. Но основная идея есть.

Ответ 3

Существует два подхода:

  • опросить файл в бесконечном цикле (как в ответе Qianjigui, но полезно положить несколько sleep внутри бесконечного цикла)
  • использовать подсистему событий ОС: kqueue на BSD, inotify в Linux

Вот статья, которую я написал об этом: 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

Ответ 4

Если вы находитесь в Linux...

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

Если вы действительно не хотели, чтобы это было Ruby script по какой-то причине.

Ответ 5

проверить file-tail gem

Ответ 6

Бедный человек подходит для быстрых вещей:

  • a Ruby script, который делает

    ARGF.each do |line|
      ...
    
  • Запуск экрана с помощью

    tail -f file | ruby script 
    

Ответ 7

Работа над идеей @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/)