log_scriptmon.ini
[constant]
monitored_file = /home/pi/logmonitor/test_events.log
counter_file = /home/pi/logmonitor/log_scriptmon.counter
script_logfile = /home/pi/logmonitor/log_scriptmon.log
max_run_diff = 600
[logfile]
# you have to prefer to combine search pattern as (MAJOR|CRITICAL|FATAL) instaed# to define more pattern in single lines
# example pattern1 = (MAJOR|CRI.*CAL|FATAL)
pattern1 = IN.O
pattern2 = CRITI.+
pattern3 = FATAL
log_scriptmon.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# log_scriptmon.py
# Skript zum Monitoring von LOG-Dateien
#
import os
import sys
import hashlib
import re
import time
import configparser
def read_configfile(fullfilepath):
configuration = configparser.ConfigParser()
configuration.read(fullfilepath)
return configuration
def file_exist(fullfilepath, error_return = 0):
if not os.path.isfile(fullfilepath):
if error_return:
print(f"ERROR: file {fullfilepath} does not exist. EXIT {error_return}")
sys.exit(error_return) # Beende das Programm mit einem Fehlercode
else:
print(f"Situation G - Die Datei {fullfilepath} existiert nicht.")
return False
return True
def datei_groesse(fullfilepath):
if os.path.isfile(fullfilepath):
groesse = os.path.getsize(fullfilepath)
return int(groesse)
else:
return -1 # Fehlercode, wenn die Datei nicht existiert
def get_basename():
skript_name = sys.argv[0]
dummy = skript_name.split("/")
x = len(dummy) - 1
skript_name = dummy[x]
dummy = skript_name.split(".")
skript_name = dummy[0]
# print(skript_name)
return skript_name
def linecounter(fullfilepath):
with open(fullfilepath, 'r') as file:
anzahl_zeilen = sum(1 for zeile in file)
return int(anzahl_zeilen)
def calc_checksum(fullfilepath, algorithm="sha256"):
# Öffne die Datei im Binärmodus und lese den Inhalt
with open(fullfilepath, 'rb') as datei:
# Wähle den gewünschten Hash-Algorithmus
hash_algorithm = hashlib.new(algorithm)
# Lese die Datei blockweise und aktualisiere den Hash
blockgroesse = 4096 # Zum Beispiel 4 KB pro Block
for block in iter(lambda: datei.read(blockgroesse), b''):
hash_algorithm.update(block)
# Gib die hexadezimale Darstellung der Checksumme zurück
checksum = hash_algorithm.hexdigest()
return checksum
def write_counterfile(fullfilepath,counterarray):
with open(fullfilepath, 'w') as file:
for element in counterarray:
file.write(str(element) + '\n')
return
def read_counterfile(fullfilepath):
with open(fullfilepath, 'r') as file:
counterarray = [line.rstrip() for line in file.readlines()]
return counterarray
def search_in_file(search_pattern, fullfilepath,start_seek = 0):
with open(fullfilepath, 'r') as file:
file.seek(start_seek)
for line in file:
for pattern in search_pattern:
if re.search(pattern, line.strip(), re.IGNORECASE):
print(f'MATCH:{line.strip()}')
return
def log(logtxt, fullfilepath):
with open(fullfilepath, 'a') as file:
logtxt = logtxt.strip()
file.write(str(logtxt) + '\n')
return
if __name__ == "__main__":
################################################
# MAIN
################################################
# READ THE INI-/CONFIGFILE
basename = get_basename() # scriptname
scriptdir = '/home/pi/logmonitor/' # scriptdir
configfile = scriptdir + basename + ".ini" # ini-file
file_exist(configfile,2) # check file exists, exit 2
cfg = read_configfile(configfile) # read ini-file/config into cfg structure
monitoredfile = cfg.get("constant", "monitored_file") # monitored logfile
counterfile = cfg.get("constant", "counter_file") # temporary data
logfile = cfg.get("constant", "script_logfile") # logfile of this script
max_run_diff = int(cfg.get("constant", "max_run_diff")) # max Zeitdiff.zw.2 Läufen
# SEARCH PATTERN
search_pattern = []
for i in range(1, 9):
pattern_key = f"pattern{i}"
if cfg.has_option("logfile", pattern_key):
search_pattern.append(cfg.get("logfile", pattern_key))
else:
break # ende der schleife, wenn ein pattern nicht mehr gefunden wird
# Standard Suchpattern, wenn kein pattern gefunden wurden
if not search_pattern:
search_pattern.append(".*")
print("start ... ")
print(f'Cache : {counterfile}')
print(f'Search Pattern: {search_pattern}')
# print(" ".join(map(str, search_pattern)))
file_exist(monitoredfile,1) # existiert logfile nicht, exit 1
print(f'Monitor on {monitoredfile}')
if file_exist(counterfile,0):
counterarray_last = read_counterfile(counterfile)
else:
counterarray_last = ["0", "0", "0", "0"]
checksum_last = counterarray_last[0]
filesize_last = int(counterarray_last[1])
anzlines_last = int(counterarray_last[2])
lastrund_last = int(counterarray_last[3])
checksum_curr = calc_checksum(monitoredfile) # C1 current checksum
filesize_curr = datei_groesse(monitoredfile) # C2 filesize
anzlines_curr = linecounter(monitoredfile) # C3 linecount
lastrund_curr = int(time.time()) # C4 last rundate
run_diff = lastrund_curr - lastrund_last
write_counterfile(counterfile,[checksum_curr, filesize_curr, anzlines_curr, lastrund_curr])
print('---------------------')
print(f'checksum_last: {checksum_last}')
print(f'filesize_last: {filesize_last} Bytes')
print(f'anzlines_last: {anzlines_last}')
print(f'lastrund_last: {lastrund_last}')
print('---------------------')
print(f'checksum_curr: {checksum_curr}')
print(f'filesize_curr: {filesize_curr} Bytes')
print(f'anzlines_curr: {anzlines_curr}')
print(f'lastrund_curr: {lastrund_curr}')
print('---------------------')
# Decision Section
if (run_diff > max_run_diff):
print(f"Situation A - first or new start with time difference over {max_run_diff} s, set seek to current file size and wait for next intervall.")
elif (checksum_last == checksum_curr):
print("Situation B - old and current file identical, nothing to do")
elif (checksum_last == "0") and (checksum_last != checksum_curr) \
and (filesize_last == 0) and (filesize_last < filesize_curr):
print("Situation C - new file, read from start")
search_in_file(search_pattern, monitoredfile, 0)
elif (anzlines_last < anzlines_curr):
print("Situation D - normal growing file, read from last position")
search_in_file(search_pattern, monitoredfile, filesize_last)
elif (anzlines_last > anzlines_curr) and (filesize_curr == 0):
print("Situation E - logrotate, new file empty - nothing to do")
elif (anzlines_last > anzlines_curr):
print("Situation F - logrotate, read file from start")
search_in_file(search_pattern, monitoredfile, 0)
print(" ... ende ")