From d747dda3f54630e1ed25aece68d5258d6fe4584c Mon Sep 17 00:00:00 2001 From: gru Date: Tue, 2 Dec 2025 10:54:53 +0100 Subject: [PATCH] Update check_xfs.py --- check_xfs.py | 96 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 41 deletions(-) diff --git a/check_xfs.py b/check_xfs.py index 8d6cfee..5cb12af 100644 --- a/check_xfs.py +++ b/check_xfs.py @@ -10,6 +10,10 @@ ESC = {"reset": "\033[0m", "red": "\033[31m", "yellow": "\033[33m", "green": "\0 def color_text(text, color): return f"{ESC[color]}{text}{ESC['reset']}" +def is_interactive(): + """Detect if running interactively (not Nagios)""" + return sys.stdout.isatty() + def run_cmd(cmd): try: return subprocess.check_output(cmd, shell=True, text=True, stderr=subprocess.STDOUT).strip() @@ -31,15 +35,17 @@ def is_xfs_mount(mount): return "xfs" in mounts_output.lower() def check_disk_usage(mount): - output = run_cmd(f"df -h {mount}") + """Use df -P for consistent POSIX output""" + output = run_cmd(f"df -P -h {mount}") for line in output.splitlines(): - if mount in line: - parts = line.split() - usage_str = parts[4] # e.g. '45%' - usage_pct = int(usage_str.strip('%')) - size = parts[1] - avail = parts[3] - return usage_pct, size, avail + parts = line.split() + if len(parts) >= 6 and mount in parts[5]: # Target is LAST column in -P + usage_str = parts[4] + if '%' in usage_str: + usage_pct = int(usage_str.strip('%')) + size = parts[1] + avail = parts[3] + return usage_pct, size, avail return None, None, None def check_xfs_repair(mount): @@ -97,78 +103,86 @@ Examples: else: target_mounts = find_xfs_mounts() - # Nagios: No mounts = UNKNOWN (3) + # Nagios: No mounts = UNKNOWN (3) - SINGLE LINE if not target_mounts: - print(color_text("UNKNOWN No XFS mount points found or specified|", "yellow")) + print("UNKNOWN No XFS mount points found or specified|") sys.exit(3) warn_threshold = args.warn_threshold crit_threshold = args.crit_threshold global_status = 0 all_perfdata = [] - - # Human-readable output (colorful) - print(color_text("Checking XFS filesystems:", "bold")) - print(f"Thresholds: WARN>{warn_threshold}%% CRIT>{crit_threshold}%%") - print("=" * 60) + + # ONLY show verbose colorful output in INTERACTIVE mode + if is_interactive(): + print(color_text("Checking XFS filesystems:", "bold")) + print(f"Thresholds: WARN>{warn_threshold}% CRIT>{crit_threshold}%") + print("=" * 60) for mount in target_mounts: - print(f"\n{color_text(mount, 'cyan')}") + if is_interactive(): + print(f"\n{color_text(mount, 'cyan')}") # Validate it's actually XFS if not is_xfs_mount(mount): - print(color_text(" UNKNOWN: Mount point not found or not XFS", "red")) + if is_interactive(): + print(color_text(" UNKNOWN: Mount point not found or not XFS", "red")) global_status = max(global_status, 3) - all_perfdata.append(f"{mount}_status=3") + all_perfdata.append(f"{mount.replace('/', '_')}_status=3") continue usage_pct, size, avail = check_disk_usage(mount) if usage_pct is None: - print(color_text(" UNKNOWN: Unable to read disk usage", "red")) + if is_interactive(): + print(color_text(" UNKNOWN: Unable to read disk usage", "red")) global_status = max(global_status, 3) - all_perfdata.append(f"{mount}_status=3") + all_perfdata.append(f"{mount.replace('/', '_')}_status=3") continue + # Usage status usage_status = 0 if usage_pct > crit_threshold: usage_status = 2 elif usage_pct > warn_threshold: usage_status = 1 - usage_color = "green" if usage_status == 0 else "yellow" if usage_status == 1 else "red" - print(f" Usage: {color_text(f'{usage_pct}%', usage_color)} (Size: {size}, Available: {avail})") + if is_interactive(): + usage_color = "green" if usage_status == 0 else "yellow" if usage_status == 1 else "red" + print(f" Usage: {color_text(f'{usage_pct}%', usage_color)} (Size: {size}, Available: {avail})") + # XFS repair check repair_ok, repair_out = check_xfs_repair(mount) - if not repair_ok: - print(color_text(" CRITICAL: XFS filesystem issues detected", "red")) - print(f" {repair_out[:200]}...") - global_status = max(global_status, 2) - xfs_status = 2 - else: - print(color_text(" XFS filesystem OK (xfs_repair dry-run)", "green")) - xfs_status = 0 + xfs_status = 2 if not repair_ok else 0 + + if is_interactive(): + if not repair_ok: + print(color_text(" CRITICAL: XFS filesystem issues detected", "red")) + else: + print(color_text(" XFS filesystem OK (xfs_repair dry-run)", "green")) # Final status for this mount mount_status = max(usage_status, xfs_status) global_status = max(global_status, mount_status) - # Nagios perfdata: metric=value;warn;crit;min;max - perf = f"used_pct={usage_pct};{warn_threshold};{crit_threshold};0;100 size={size} avail={avail} xfs_repair={xfs_status}" + # Nagios perfdata format + mount_name = mount.replace('/', '_').replace(' ', '_') + perf = f"{mount_name}_used_pct={usage_pct};{warn_threshold};{crit_threshold};0;100 size={size} avail={avail} xfs_status={xfs_status}" all_perfdata.append(perf) - perfdata = " ".join(all_perfdata) + perfdata = "| " + " ".join(all_perfdata) status_text = {0: "OK", 1: "WARNING", 2: "CRITICAL", 3: "UNKNOWN"} - # Colorful human output - status_color = "green" if global_status == 0 else "yellow" if global_status == 1 else "red" - print("\n" + "=" * 60) - print(color_text(f"FINAL STATUS: {status_text[global_status]}", status_color)) - print(f"| {perfdata}") + # ALWAYS: Clean Nagios output FIRST LINE (parseable) + print(f"{status_text[global_status]} XFS check: {len(target_mounts)} mount(s){perfdata}") - # NAGIOS: Clean single-line output (no colors, parseable) - print(f"\n{status_text[global_status]} XFS check complete| {perfdata}") + # ONLY interactive: Additional colorful summary + if is_interactive(): + status_color = "green" if global_status == 0 else "yellow" if global_status == 1 else "red" + print("\n" + "=" * 60) + print(color_text(f"FINAL STATUS: {status_text[global_status]}", status_color)) + print(f"{perfdata}") - # Nagios standard exit codes + # Nagios standard exit codes: 0=OK, 1=WARNING, 2=CRITICAL, 3=UNKNOWN sys.exit(global_status) if __name__ == "__main__":