Python Skript zur Überwachung einer Logdatei

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

Die Kommentarfunktion ist geschlossen.