Welcome, guest | Sign In | My Account | Store | Cart

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

Python, 92 lines
 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.

3 comments

Paul Miller 18 years, 9 months ago  # | flag

An idea. Why not do something like this for repeated messages:

05-21-05 03:13 AM: Updating database.
05-21-05 03:15 AM: Last entry repeated 20 times.

?

Bibha Tripathi (author) 18 years, 9 months ago  # | flag

very nice... this can be done by remembering the last logged line until a new/different line is logged.