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 ")