#!/usr/bin/env python from optparse import OptionParser, Option import time, sys __cmdParser__ = OptionParser() __cmdParser__.add_option("-i", "--logfile", action="append", \ dest="logfiles", type="string", \ help="system log to parse") __cmdParser__.add_option("-v", "--verbose", action="count", \ dest="verbosity", \ help="How obnoxious we're being about telling the user what we're doing.") (__cmdLineOpts__, __cmdLineArgs__)=__cmdParser__.parse_args() class logfile_class: def __init__(self,fname): self.events = [] self.curline = "" self.prevline = "" self.eof = False self.hostname = "" self.fname = fname self.fp = open(fname) first_line = self.fp.readline().strip() multip = 1 readblock = 64 while True: self.fp.seek(-readblock * multip,2) newlnpos = self.fp.read(readblock).find("\n") if newlnpos > 0 and newlnpos < readblock - 1: self.fp.seek(-readblock * multip + newlnpos +1, 2) break multip+=1 last_line = self.fp.readline().strip() self.fp.seek(0) # let's convert the first and last timestamp to something useful # Jul 22 04:48:05 self.time_begin = time.strptime(first_line[0:15], "%b %d %H:%M:%S") self.time_end = time.strptime( last_line[0:15], "%b %d %H:%M:%S") # FIXME: check that first_line < last_line def readline(self): self.curline_pos = self.fp.tell() self.prevline = self.curline self.curline = self.fp.readline().strip() if len(self.curline) == 0: self.eof = True return self.curline def seek(self,pos): self.fp.seek(pos) self.eof = False self.curline = "" def parse(self): self.seek(0) while not self.eof: self.readline() self.parse_line() self.seek(0) def curmessage(self): return self.curline[17 + self.curline[16:].find(" "):] def parse_line(self): # is valid log line ? if not self.time_current(): return # store hostname, if we don't already have it if len(self.hostname) == 0: self.curline.split()[3] # system is booting if self.curmessage().startswith("kernel: Linux version"): self.add_event("system boot") # hostname has changed if len(self.hostname) and self.hostname != self.curline.split()[3]: self.add_event("hostname changed") self.hostname = self.curline.split()[3] # the clock is wrong wrong if self.prevline and time.strptime(self.prevline[0:15], "%b %d %H:%M:%S") > self.time_current(): self.add_event("clock is messed up") def add_event(self, message): self.events.append( (self.curline_pos,len(self.curline),message) ) def time_current(self): if len(self.curline) == 0: return None try: return time.strptime(self.curline[0:15], "%b %d %H:%M:%S") except ValueError: print "could not parse time", self.curline return False logs = [] for logname in __cmdLineOpts__.logfiles: log = logfile_class(logname) log.parse() logs.append(log) print """ """ print '' print """ """ previous_date = None inc = 0 while True: # who is next ? lowest_date = None for log in logs: if log.eof: continue if not len(log.curline): log.readline() if lowest_date == None or log.time_current() < lowest_date: lowest_date = log.time_current() if lowest_date == None: # all logs are EOF break if inc == 0 or inc % 200 == 0: print """""" if not previous_date or time.strftime("%b %d", previous_date) != time.strftime("%b %d", lowest_date): print """""" % time.strftime("%A, %B %d", lowest_date) if inc % 2 == 0: row_class = "spec" else: row_class = "altspec" # FIXME: if this tick has an event, add if not previous_date or previous_date != lowest_date: print """""" else: print """""" for log in logs: if log.time_current() == lowest_date: print " " log.curline = "" else: print " " # print log.curline_pos, time.strftime("%b %d %H:%M:%S", log.time_current()), log.curmessage() print " " previous_date = lowest_date inc += 1 print "
Generated by SOS htmlogger 1.0 on March 16th 2008
Time of Eventnode-1node-2node-3
%s
""" + time.strftime("%H:%M:%S", lowest_date) + """
""" + time.strftime("%H:%M:%S", lowest_date) + """" + log.curmessage() + "
"