From: "Berger, Daniel" Date: 2002-08-01T22:11:29+09:00 Subject: RE: A very basic tail -f implementation > -----Original Message----- > From: Curt Sampson [mailto:cjs@cynic.net] > On Thu, 1 Aug 2002, James F.Hranicky wrote: > > > On Thu, 1 Aug 2002 21:23:09 +0900 > > "Berger, Daniel" wrote: > > > > > > - Check for rotation by checking for changes in > the inode number > > ... > > That's true, you just have to stat the actual filename everytime and > > check against the current filehandle. > > Right. You also ought to check the device number, in case the file > is somewhow moved to another device and ends up with the same inode > number. At least, that's what I did when I added the '-F' option > to tail(1) in NetBSD. Maybe I'm just anal-retentive. :-) Heh. I came across that while reading some usenet posts on a similar subject. > > Also, you might want to check to see if the file has been shortened, > in case the writer truncates it and starts writing again at the > beginning. Wow. Thorough. Well, here's what I had come up with so far, using one of Paul Brannan's posts as a starting point. Between all of us, we should have something pretty good and thorough soon. :) class Tail < File def initialize(file,sleeptime=10) @file = File.open(file,"r") @sleeptime = sleeptime end ############################################################## # In block form, read a line at a time in a loop. Otherwise, # just return the number of lines specified as an array. ############################################################## def tail(max=10) if block_given? yield get_lines(max) loop do line = @file.gets yield line unless line.nil? if @file.eof? @file.seek(@file.pos) end sleep @sleeptime end else get_lines(max) end end ####################################################################### # Grab the last 'max' lines (default is 10). This method was created # for two reasons. First, even a "tail -f" reads the last 10 lines. # Second, it's separated from the tail() method in the event the # programmer just wants a "plain" tail. ####################################################################### def get_lines(max) @file.seek(0,IO::SEEK_END) newline_count = 0 while newline_count < max begin @file.pos -= 2 rescue Errno::EINVAL break end break if @file.eof? if @file.getc.chr == "\n" newline_count += 1 end end @file.readlines end end =begin = Description Tail - A pure-Ruby implementation of the 'tail' command. Tail is a subclass of File. = Overview t = Tail.new("somefile.txt") # To imitate 'tail -f', use a block t.tail do |line| puts line end # To simply grab the last X lines, don't use a block a = t.tail(20) puts a # or even t.tail(20).each{ |line| puts line } =end