import ast
import logging.handlers
import types
+import traceback # debugging only
reload(sys)
sys.setdefaultencoding('utf-8') # force utf-8 because anything else should die
'title': 'logparse',
'maxlist': 10,
'maxcmd': 3,
+ 'resolve-domains': 'fqdn',
'mail': {
'to': '',
'from': '',
'port': 7634,
'show-model': False,
},
+ 'apache': {
+ 'resolve-domains': '',
+ },
+ 'sshd': {
+ 'resolve-domains': '',
+ },
+ 'smbd': {
+ 'resolve-domains': '',
+ },
+ 'httpd': {
+ 'resolve-domains': '',
+ },
'du-paths': ['/', '/etc', '/home'],
'hostname-path': '/etc/hostname',
'logs': {
debugfunc = parser.parse_args().function
if debugfunc is not None:
logger.debug("executing a single function: " + debugfunc)
- try:
- logger.debug((debugfunc + ': ' + eval(debugfunc)))
- sys.exit()
- except Exception as e:
- sys.exit("debug function failed with error " + e)
- logger.debug("finished executing debug function")
+ eval(debugfunc)
+ sys.exit()
if not config['mail']['to']:
logger.info("no recipient address provided, outputting to stdout")
else:
logger.info("email will be sent to " + config['mail']['to'])
+ global LOCALDOMAIN
+ LOCALDOMAIN = getlocaldomain()
+
global pathfilter
global pathpattern
pathfilter = {"auth": config['logs']['auth'], "cron": config['logs']['cron'], "sys": config['logs']['sys'], "postfix": config['logs']['postfix'], "smb": config['logs']['smb'], "zfs": config['logs']['zfs'], "alloc": config['logs']['alloc'], "httpd": config['logs']['httpd'], "header": config['header']}
hn = re.search('^(.*)\n*', hnfile.read()).group(1)
return hn
+def getlocaldomain(): # get the parent fqdn of current server
+ domain = socket.getfqdn().split('.', 1)
+ if len(domain) == 2:
+ logger.warning('Could not get domain of this server, only hostname. Please consider updating /etc/hosts')
+ return ''
+ else:
+ return domain[-1]
+
+def resolve(ip, fqdn = 'host-only'): # try to resolve an ip to hostname
+ # Possible values for fqdn:
+ # fqdn show full hostname and domain
+ # fqdn-implicit show hostname and domain unless local
+ # host-only only show hostname
+ # ip never resolve anything
+ # resolve-domains defined in individual sections of the config take priority over global config
+
+ if not fqdn:
+ fqdn = config['resolve-domains']
+
+ if fqdn == 'ip':
+ return(ip)
-def resolve(ip, fqdn = False): # try to resolve an ip to hostname
try:
socket.inet_aton(ip) # succeeds if text contains ip
hn = socket.gethostbyaddr(ip)[0] # resolve ip to hostname
- return(hn if fqdn else hn.split('.')[0])
- except OSError:
- # already a hostname
- logger.debug(ip + " is already a hostname")
- return(ip)
+ if fqdn == 'fqdn-implicit' and hn.split('.', 1)[1] == LOCALDOMAIN:
+ return(hn.split('.')[0])
+ elif fqdn == 'fqdn' or fqdn == 'fqdn-implicit':
+ return(hn)
+ elif fqdn == 'host-only':
+ return(hn.split('.')[0])
+ else:
+ logger.warning("invalid value for fqdn config")
+ return(hn)
except socket.herror:
# cannot resolve ip
logger.debug(ip + " cannot be found, might not exist anymore")
return(ip)
- except:
- logger.debug("failed to resolve hostname for " + ip)
+ except (OSError, socket.error): # socket.error for Python 2 compatibility
+ # already a hostname
+ logger.debug(ip + " is already a hostname")
+ return(ip)
+ except Exception as err:
+ logger.warning("failed to resolve hostname for " + ip + ": " + str(err))
return(ip) # return ip if no hostname exists
def plural(noun, quantity): # return "1 noun" or "n nouns"
user = entry.group(1)
ip = entry.group(2)
- userhost = user + '@' + resolve(ip)
+ userhost = user + '@' + resolve(ip, fqdn=config['sshd']['resolve-domains'])
exists = [i for i, item in enumerate(users) if re.search(userhost, item[0])]
if (exists == []):
users.append([userhost, 1])
for line in accesslog.split('\n'):
fields = re.search('^(\S*) .*GET (\/.*) HTTP/\d\.\d\" 200 (\d*) \"(.*)\".*\((.*)\;', line)
try:
- ips.append(resolve(fields.group(1), fqdn=True))
+ ips.append(resolve(fields.group(1), fqdn=config['httpd']['resolve-domains']))
files.append(fields.group(2))
useragents.append(fields.group(5))
data_b += int(fields.group(3))
pass
else:
logger.warning("error processing httpd access log: " + str(error))
+ traceback.print_exc()
logger.debug(str(data_b) + " bytes transferred")
data_h = parsesize(data_b)
writetitle("apache")
# find the machine (ip or hostname) that this file represents
ip = re.search('log\.(.*)', file).group(1) # get ip or hostname from file path (/var/log/samba/log.host)
- host = resolve(ip)
- if (host == ip): # if ip has disappeared, fall back to a hostname from logfile
+ host = resolve(ip, fqdn=config['smbd']['resolve-domains'])
+ if (host == ip and (config['smbd']['resolve-domains'] or config['resolve-domains']) != 'ip'): # if ip has disappeared, fall back to a hostname from logfile
newhost = re.findall('.*\]\@\[(.*)\]', readlog(file))
if (len(set(newhost)) == 1): # all hosts in one file should be the same
host = newhost[0].lower()
logger.debug("starting zfs section")
opentag('div', 1, 'zfs', 'section')
zfslog = readlog('zfs')
- logger.debug("got zfs logfile")
pool = re.search('.*---\n(\w*)', zfslog).group(1)
- scrub = re.search('.*scrub repaired (\d*) in \d*h\d*m with (\d*) errors on (\S*\s)(\S*)\s(\d+\s)', zfslog)
+ scrub = re.search('.*scrub repaired (\d*).* in .*\d*h\d*m with (\d*) errors on (\S*\s)(\S*)\s(\d+\s)', zfslog)
iostat = re.search('.*---\n\w*\s*(\S*)\s*(\S*)\s', zfslog)
scrubrepairs = scruberrors = scrubdate = None
try:
scrubrepairs = scrub.group(1)
scruberrors = scrub.group(2)
scrubdate = scrub.group(3) + scrub.group(5) + scrub.group(4)
- except:
- logger.debug("error getting scrub data")
+ except Exception as e:
+ logger.debug("error getting scrub data: " + str(e))
alloc = iostat.group(1)
free = iostat.group(2)
writetitle("zfs")
# Start it like this (bash): sudo hddtemp -d /dev/sda /dev/sdX...
received = ''
- sumtemp = 0
+ sumtemp = 0.0
data = ""
output = []