Смотреть/читать растущий файл журнала
У меня есть файл журнала, который постоянно растет. Как я могу смотреть и анализировать его с помощью Ruby script?
script будет анализировать каждую новую строку, поскольку она записывается в файл и выводит что-то на экран, когда новая строка содержит строку "ERROR"
Ответы
Ответ 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
Бедный человек подходит для быстрых вещей:
Ответ 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/)