A very basic tail -f implementation

Hi all,

I’ve been playing with a Ruby implementation of the *nix ‘tail’ command. Here’s
what I’ve come up with so far. I thought I’d put it out there for comment and see
what people think.

It doesn’t do anything fancy - it’s not nearly as smart as it’s Perl equivalent yet,
for example. But, it works.

Requires 1.7.2 (for the sysseek method).

While this is running, try doing

“echo ‘sometext’ >> test.txt” once in a while

require 'tail’
t = Tail.new(“test.txt”) # Or whatever

Ctrl-C to exit

while true
puts t.read
end

Da code

class Tail

attr_accessor :file, :buffer, :interval

def initialize(file, buffer=8192, interval=10)
@file = file
@buffer = buffer
@interval = interval

  @fh = File.open(file,"r")
  @fh.sysseek(-1,2)

end

def read
begin
return @fh.sysread(buffer).tr("\n","")
rescue EOFError
@fh.sysseek(-1,2)
sleep interval
retry
end
end
end

I have an implementation of tail -f that looks similar, except it
doesn’t seek to the end of file at start, and it’s called like this:

File.open(filename) do |input|
tail_f(input) do |line|
puts line
end
end

Two advantages here:

  1. If an exception is raised from inside the block, the file will be
    properly closed.
  2. I get my input line-by-line, which imo is much more useful than
    buffersize-by-buffersize.

Some advantages of your implementation:

  1. It is an object, and acts somewhat like an IO object, thus
  2. If RCR#65 (http://www.rubygarden.org/article.php?sid=179) were
    accepted, it could easily be modified to inherit from IO and make
    this class act just like a pipe.
  3. The sleep interval and buffer size are adjustable.

My implementation:

def clearerr(io)
offset = io.tell
io.seek(offset)
end

def tail_f(input)
loop do
line = input.gets
yield line if not line.nil?
if input.eof? then
sleep 1
clearerr(input)
end
end
end

Paul

···

On Tue, Jul 30, 2002 at 05:15:25AM +0900, Daniel Berger wrote:

Ctrl-C to exit

while true
puts t.read
end