class NotifiedTail
Tail lines in a given file Inspired by rubyforadmins.com/reading-growing-files
Attributes
file_path[R]
Public Class Methods
tail(file_path, opts={}, &on_line)
click to toggle source
Yields complete lines, one at a time. Works even if file doesn't exist yet. @param file_path
[String] The file to tail @option opts [Boolean] seek_end (true)
If true, seeks to the end of the file before reporting lines. Otherwise, reports all lines starting at the beginning of the file.
@option opts [Boolean] force_poll (false)
Poll even if inotify or kqueue are available
# File lib/notified_tail.rb, line 15 def self.tail(file_path, opts={}, &on_line) new.tail(file_path, opts, &on_line) end
Private Class Methods
get_ruby_platform()
click to toggle source
# File lib/notified_tail.rb, line 94 def self.get_ruby_platform RUBY_PLATFORM end
Public Instance Methods
stop()
click to toggle source
# File lib/notified_tail.rb, line 36 def stop @queue.stop if @queue @queue = nil @stopped = true end
tail(file_path, opts={}, &on_line)
click to toggle source
# File lib/notified_tail.rb, line 19 def tail(file_path, opts={}, &on_line) @file_path = file_path @stopped = false seek_end = opts.fetch(:seek_end, true) @force_poll = opts.fetch(:force_poll, false) sleep(0.25) until File.exists?(file_path) File.open(file_path) do |file| unreported_line = '' if seek_end file.seek(0, IO::SEEK_END) else read_and_report_lines(file, unreported_line, &on_line) end when_modified(file_path) { read_and_report_lines(file, unreported_line, &on_line) } end end
Private Instance Methods
line_ending?(c)
click to toggle source
# File lib/notified_tail.rb, line 98 def line_ending?(c) c == "\n" || c == "\r" end
poll(file_path, &block)
click to toggle source
# File lib/notified_tail.rb, line 79 def poll(file_path, &block) last_mtime = File.mtime(file_path) last_notify_time = nil until @stopped do sleep(0.5) mtime = File.mtime(file_path) changed = mtime != last_mtime if changed || last_notify_time == nil || (Time.now - last_notify_time) > 5 last_mtime = mtime last_notify_time = Time.now block.call end end end
read_and_report_lines(file, unreported_line, &on_line)
click to toggle source
# File lib/notified_tail.rb, line 44 def read_and_report_lines(file, unreported_line, &on_line) loop do c = file.readchar if line_ending?(c) on_line.call(unreported_line.dup) unreported_line.clear while (c = file.readchar) && line_ending?(c) do; end end unreported_line << c end rescue EOFError # done for now end
when_modified(file_path, &block)
click to toggle source
# File lib/notified_tail.rb, line 58 def when_modified(file_path, &block) if @force_poll poll(file_path, &block) else case NotifiedTail.get_ruby_platform when /bsd/, /darwin/ require 'rb-kqueue' @queue = KQueue::Queue.new @queue.watch_file(file_path, :extend) { block.call } @queue.run unless @stopped when /linux/ require 'rb-inotify' @queue = INotify::Notifier.new @queue.watch(file_path, :modify) { block.call } @queue.run unless @stopped else poll(file_path, &block) end end end