I have chose GeSH for convenience and for the fact that I do not really enjoy much Javascript in my pages.
The tool does a "tail -f" on multiple files - like the output of a RollingFileAppender.
UPDATE: In the meanwhile I have found that Alex Gorbatchev's SyntaxHighlighter offers a hosting for it's brushes. In spite of my JS phobia I have chosen it over GeSH as the output looks way better.
#!/usr/bin/env python
import glob
import optparse
import os
import signal
import stat
import sys
import time
files = {}
def info(*text):
if options.verbose==True:
for token in text:
print token,
print
def handler(sig, frame):
if sig==signal.SIGUSR1:
print "*** Caught USR1 ***"
print "Watched files are: "
for f in files.keys():
print f, " ",
print
if sig==signal.SIGINT:
sys.exit(0)
class GenericLogFile:
def __init__(self, name, label = False):
self.name = name
self.label = ""
if label:
self.label=self.name+":"
self.open()
def close(self):
self.file.close()
def open(self):
self.file = open(self.name, "r")
self.file.seek(0, 2)
self.lastpos = self.file.tell()
self.mtime = os.stat(self.name)[stat.ST_MTIME]
self.inode = os.stat(self.name)[stat.ST_INO]
def reopen(self):
self.open()
self.file.seek(0, 0)
def tell(self):
return self.file.tell()
def size(self):
return os.stat(self.name)[stat.ST_SIZE]
def changed(self):
return os.stat(self.name)[stat.ST_INO]!=self.inode
def tail(self):
#Inode changed
if self.changed():
info("***File ", self.name, " was changed")
self.close()
self.reopen()
size = self.size()
pos = self.tell()
#File truncated
if size<pos:
info("***File ", self.name, " was truncated(size=",size," pos=",pos,")")
self.close()
self.open()
#Data written since we have last checked
if pos!=size:
if self.label=="":
info("***File ", self.name)
#Display all remaining lines
while True:
line = self.file.readline()
if line!="":
print self.label+line,
else:
break
help="""
DESCRIPTION
This program works as tail -f for multiple files.
files - any kind of file. They can be specified using shell patterns (*/?)
-v - verbose output
-l - label each line with the file ith has been read from
-h - prints this help
WARNING
Please enclose the filename patterns between single/double quotes in order to prevent
shell globbing.
SIGNALS
USR1 - dumps a list of the open files
"""
def init():
global options, args, parser, config
#Initialization
parser = optparse.OptionParser(help)
parser.add_option("-l", "--label", action="store_true", dest="label", help="label each line with the name of the file from that it was read")
parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="print more verbose diagnostics")
(options, args) = parser.parse_args()
signal.signal(signal.SIGUSR1, handler)
signal.signal(signal.SIGINT, handler)
if __name__=='__main__':
init()
if len(args)!=0:
lst = glob.glob(sys.argv[1])
if len(lst)==0:
print "WARNING: No file matched the input yet!"
else:
parser.error("Incorrect number of arguments")
parser.print_help()
#Initial situation
#Get all the files already present
for f in lst:
if not f in files:
print "Added ", f
files[f] = GenericLogFile(f, options.label)
#Main loop
while True:
lst = glob.glob(pattern)
for f in files.keys():
if f not in lst:
#We no longer need this file...
info("Deleted ", f)
del files[f]
continue
else:
files[f].tail()
for f in lst:
if not f in files:
info("Added ", f)
#This is a file that appeared during program run.
#We have to print it all
files[f] = GenericLogFile(f, options.label)
files[f].reopen()
files[f].tail()
time.sleep(1)
No comments:
Post a Comment