I needed to write a Python script for a "tail -f" that displays log entries from multiple files in a given directory. The display had to be in chronological order, the first column of each log file being timestamp of the log. It should work for any type of files.
Usage: python tail_m.py directoryname
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | '''Does tail -f on log files in a given directory.
The display is in chronological order of the logged lines,
given that the first column of log files is timestamp.
It can be altered to fit other formats too'''
import time, os, sys, getopt
def Walk( root, recurse=0, pattern='*', return_folders=0 ):
import fnmatch, os, string
# initialize
result = []
# must have at least root folder
try:
names = os.listdir(root)
except os.error:
return result
# expand pattern
pattern = pattern or '*'
pat_list = string.splitfields( pattern , ';' )
# check each file
for name in names:
fullname = os.path.normpath(os.path.join(root, name))
# grab if it matches our pattern and entry type
for pat in pat_list:
if fnmatch.fnmatch(name, pat):
if os.path.isfile(fullname) or (return_folders and os.path.isdir(fullname)):
result.append(fullname)
continue
# recursively scan other folders, appending results
if recurse:
if os.path.isdir(fullname) and not os.path.islink(fullname):
result = result + Walk( fullname, recurse, pattern, return_folders )
return result
def main():
dirname = sys.argv[1]
print dirname
files = Walk(dirname, 1, '*', 1)
if len(files) == 0:
print 'Empty directory!'
sys.exit(1)
#Set the filename and open the file
for filename in files:
print 'printing file names', filename
latest = ""
while 1:
for filename in files:
file = open(filename,'r')
#Find the size of the file and move to the end
st_results = os.stat(filename)
#print st_results
st_size = st_results[6]
#print st_size
file.seek(st_size -124)
l = file.read()
xin = l.find('\n')
l = l[xin:]
ts = l[0:24]
ts = ts.strip()
where = file.tell()
if not l:
time.sleep(1)
file.seek(where)
else:
if ts > latest:
latest = ts.strip()
print l.strip() #Print the latest logged line
if __name__ == '__main__':
main()
|
Thanks for tail.py and dirwalk.py,as you'll notice, I've used those as ingredients :D.
Tags: files
An idea. Why not do something like this for repeated messages:
?
very nice... this can be done by remembering the last logged line until a new/different line is logged.
Similar but cleaner: http://code.activestate.com/recipes/577968-log-watcher-tail-f-log/