Hi all,
Here’s the latest incarnation I’ve come up with, stealing bits of code from James Hranicky and
ideas from Curt Sampson.
The inode and dev checks are untested, so if there’s a logic flaw there, please let me know.
Opions & feedback welcome/desired.
Regards,
Dan
Da code!
class Tail < File
def initialize(file,sleeptime=10)
@filename = file
@fh = File.open(file,“r”)
@sleeptime = sleeptime
@ino = @fh.stat.ino
@dev = @fh.stat.dev
@ino_changed = false
@dev_changed = false
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 = @fh.gets
yield line unless line.nil?
if @fh.eof?
check_move()
if (@ino_changed == true) || (@dev_changed == true)
@fh.close
initialize(@filename,@sleeptime)
next
end
@fh.seek(@fh.pos)
end
sleep @sleeptime
end
else
get_lines(max)
end
end
def check_move
begin
if(File.stat(@filename).ino != @ino)
@ino_changed = true
end
if(File.stat(@filename).dev != @dev)
@dev_changed = true
end
rescue Errno::ENOENT
retry
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)
@fh.seek(0,IO::SEEK_END)
newline_count = 0
while newline_count < max
begin
@fh.pos -= 2
rescue Errno::EINVAL
break
end
break if @fh.eof?
if @fh.getc.chr == "\n"
newline_count += 1
end
end
@fh.readlines
end
end