diff --git a/VERSION.txt b/VERSION.txt index 1d71ef9..48b9990 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -0.3 \ No newline at end of file +0.31 diff --git a/src/tailer/__init__.py b/src/tailer/__init__.py index eb44e96..fd6ec17 100644 --- a/src/tailer/__init__.py +++ b/src/tailer/__init__.py @@ -1,6 +1,7 @@ import re import sys import time +import os if sys.version_info < (3,): range = xrange @@ -150,14 +151,20 @@ def head(self, lines=10): else: return [] - def follow(self, delay=1.0): + def follow(self, delay=1.0, filename=None): """\ Iterator generator that returns lines as data is added to the file. Based on: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/157035 + + If filename is passed, will make sure that the file has not been deleted, + or that it has not been rotated. This feature is useful for compatability with + logrotate. """ trailing = True - + if filename is not None: + curino = os.fstat(self.file.fileno()).st_ino + while 1: where = self.file.tell() line = self.file.readline() @@ -177,9 +184,32 @@ def follow(self, delay=1.0): trailing = False yield line else: + should_seek = True + if filename is not None: + reopen = False + try: + if os.stat(filename).st_ino != curino: + self.file.close() + reopen = True + except: + # file probably has been deleted + curino = None + reopen = True + + if reopen: + try: + self.file = open(filename, "r") + curino = os.fstat(self.file.fileno()).st_ino + should_seek = False + except: + # a new file does not exist yet + time.sleep(delay) + + if should_seek: + self.seek(where) + time.sleep(delay) + trailing = True - self.seek(where) - time.sleep(delay) def __iter__(self): return self.follow() @@ -213,7 +243,7 @@ def head(file, lines=10): """ return Tailer(file).head(lines) -def follow(file, delay=1.0): +def follow(file, delay=1.0, filename=None): """\ Iterator generator that returns lines as data is added to the file. @@ -233,7 +263,7 @@ def follow(file, delay=1.0): >>> fo.close() >>> os.remove('test_follow.txt') """ - return Tailer(file, end=True).follow(delay) + return Tailer(file, end=True).follow(delay, filename) def _test(): import doctest