#!/usr/bin/env python3 import subprocess import re import sys import argparse from datetime import datetime def get_dmesg_output(severities): """ Uruchamia polecenie dmesg z określonymi poziomami krytyczności. W przypadku błędu zwraca status UNKNOWN (kod 3). """ try: cmd = ["dmesg", "-T", "-l", severities] result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True) return result.stdout.splitlines() except subprocess.CalledProcessError as e: print("UNKNOWN - Błąd podczas uruchamiania dmesg:", e) sys.exit(3) def filter_messages(messages, whitelist_regex, date_str): """ Filtruje komunikaty: - uwzględnia tylko linie zawierające dzisiejszą datę, - ignoruje linie pasujące do whitelist. """ filtered = [] for line in messages: if date_str in line and not whitelist_regex.search(line): filtered.append(line) return filtered def tail_messages(messages, tail_count): """ Zwraca ostatnie tail_count komunikatów. """ return messages[-tail_count:] if messages else [] def main(): parser = argparse.ArgumentParser(description="NRPE check: Monitorowanie krytycznych komunikatów dmesg.") parser.add_argument("--severities", type=str, default="err,alert,emerg,crit", help="Poziomy krytyczności dmesg (domyślnie: err,alert,emerg,crit).") parser.add_argument("--tail", type=int, default=5, help="Liczba ostatnich komunikatów do wyświetlenia (domyślnie 5).") args = parser.parse_args() # Definicja whitelist – komunikaty ignorowane, m.in. specyficzne dla Proxmox whitelist_patterns = [ r"microcode:", r"Firmware Bug", r"i8042: No controller", r"Odd, counter constraints enabled but no core perfctrs detected", r"Failed to access perfctr msr", r"echo 0 > /proc/sys", r"EXT4-fs.*(write access unavailable|mounted filesystem .* ro without journal|unmounting filesystem)", r"We currently don't support analog TV or stream capture on dual tuners" ] whitelist_regex = re.compile("|".join(whitelist_patterns)) # Pobranie dzisiejszej daty w formacie odpowiadającym dmesg -T (np. "Wed Mar 23") today = datetime.now().strftime("%a %b %e") messages = get_dmesg_output(args.severities) filtered = filter_messages(messages, whitelist_regex, today) tail_filtered = tail_messages(filtered, args.tail) if not tail_filtered: print("OK - Wszystko w porządku.") sys.exit(0) else: # Łączymy komunikaty w jedną linię, aby Nagios miał czytelny output output = " | ".join(tail_filtered) print(f"CRITICAL - Krytyczne komunikaty dmesg: {output}") sys.exit(2) if __name__ == "__main__": main()