class File
module Tail
# This is an easy to use Logfile class that includes
# the File::Tail module.
#
# === Usage
# The unix command "tail -10f filename" can be emulated like that:
# File::Tail::Logfile.open(filename, :backward => 10) do |log|
# log.tail { |line| puts line }
# end
#
# Or a bit shorter:
# File::Tail::Logfile.tail(filename, :backward => 10) do |line|
# puts line
# end
#
# To skip the first 10 lines of the file do that:
# File::Tail::Logfile.open(filename, :forward => 10) do |log|
# log.tail { |line| puts line }
# end
#
# The unix command "head -10 filename" can be emulated like that:
# File::Tail::Logfile.open(filename, :return_if_eof => true) do |log|
# log.tail(10) { |line| puts line }
# end
class Logfile < File
include File::Tail
# This method creates an File::Tail::Logfile object and
# yields to it, and closes it, if a block is given, otherwise it just
# returns it. The opts hash takes an option like
# * :backward => 10
to go backwards
# * :forward => 10
to go forwards
# in the logfile for 10 lines at the start. The buffersize
# for going backwards can be set with the
# * :bufsiz => 8192
option.
# To define a callback, that will be called after a reopening occurs, use:
# * :after_reopen => lambda { |file| p file }
#
# Every attribute of File::Tail can be set with a :attributename =>
# value
option.
def self.open(filename, opts = {}, &block) # :yields: file
file = new filename
opts.each do |o, v|
writer = o.to_s + "="
file.__send__(writer, v) if file.respond_to? writer
end
if opts.key?(:wind) or opts.key?(:rewind)
warn ":wind and :rewind options are deprecated, "\
"use :forward and :backward instead!"
end
if backward = opts[:backward] || opts[:rewind]
(args = []) << backward
args << opt[:bufsiz] if opts[:bufsiz]
file.backward(*args)
elsif forward = opts[:forward] || opts[:wind]
file.forward(forward)
end
if opts[:after_reopen]
file.after_reopen(&opts[:after_reopen])
end
if block_given?
begin
block.call file
ensure
file.close
nil
end
else
file
end
end
# Like open, but yields to every new line encountered in the logfile in
# +block+.
def self.tail(filename, opts = {}, &block)
if ([ :forward, :backward ] & opts.keys).empty?
opts[:backward] = 0
end
open(filename, opts) do |log|
log.tail { |line| block.call line }
end
end
end
end
end