diff --git a/check_memory b/check_memory old mode 100644 new mode 100755 index 6b24d83..fe20a7d --- a/check_memory +++ b/check_memory @@ -1,80 +1,131 @@ -#!/usr/bin/python +#!/usr/bin/env python3 -#### Author : Taha Ali +#### Original Author : Taha Ali, +#### Modified by: Dan Barker #### Created: 09/01/2015 -#### Contact: tahazohair@gmail.com +#### Updated: 03/05/2024 (Python 3) +#### Contact: tahazohair@gmail.com, github.com/danbarker ### ## -# Summary: this is script or program calculates how much total memory is available. -# it also takes in account for buffers and Caches. Defaults are set at 85% for warning and 90% for critical +# Summary: This script calculates how much total and swap memory is available. +# It also takes into account buffers and caches. Defaults are set at 85% for warning and 90% for critical +# for both RAM and swap memory. ## ### import sys -import optparse +import argparse __author__ = 'bindas' -# nagios exit status +# Nagios exit status OK = 0 WARN = 1 CRIT = 2 UNKNOWN = 3 -# Parameters optioning -parser = optparse.OptionParser( - usage="%prog -c -w \nAuthor:\t\tTaha Ali \nContact:\ttahazohair@gmail.com", - prog='check_mem.py', - version='1.0', +parser = argparse.ArgumentParser( + usage="%(prog)s -c -w -sc -sw ", + prog='check_memory', + description='This script calculates available system and swap memory accounting for buffers and caches.' ) -parser.add_option('-c', '--critical', - dest="critical", - default="90", - type="float", - help="critical value in percentage, Default set at 90%", - ) -parser.add_option('-w', '--warning', - dest="warning", - default="85", - type="float", - help="warning value in percentage, Default set at 85%", - ) -(options, args) = parser.parse_args() - -# get data from parameters optioning and feed it into warning and critical variables -critical = options.critical -warning = options.warning +parser.add_argument('-c', '--critical', + dest="critical_pc", + default=90.0, + type=float, + help="Critical value in percentage for RAM usage, default set at 90") +parser.add_argument('-w', '--warning', + dest="warning_pc", + default=85.0, + type=float, + help="Warning value in percentage for RAM usage, default set at 85") +parser.add_argument('-sc', '--swap_critical', + dest="swap_critical_pc", + default=90.0, + type=float, + help="Critical value in percentage for swap usage, default set at 90") +parser.add_argument('-sw', '--swap_warning', + dest="swap_warning_pc", + default=85.0, + type=float, + help="Warning value in percentage for swap usage, default set at 85") +options = parser.parse_args() + +critical = options.critical_pc +warning = options.warning_pc +swap_critical = options.swap_critical_pc +swap_warning = options.swap_warning_pc + +# Read memory info +entry = {} with open('/proc/meminfo', 'r') as memfile: - entry = {} for line in memfile: - line = line.strip() - line = line.replace('kB', '') - if not line: break - name, value = map(str.strip, line.split(':')) - entry[name] = value - -# get and calculate free memory value -free = int(entry['MemFree']) + int(entry['Buffers']) + int(entry['Cached']) -# get total memory value -total = int(entry['MemTotal']) + line = line.strip().replace('kB', '').split(':') + if line[0]: + entry[line[0].strip()] = int(line[1].strip()) +# Calculate free memory +free = entry['MemFree'] + entry.get('Buffers', 0) + entry.get('Cached', 0) +# Total memory +total = entry['MemTotal'] +# Calculate swap usage +swap_free = entry['SwapFree'] +swap_total = entry['SwapTotal'] def mem_load(): - # change to percentage - use_percent = 100 - ((free * 100) / total) - if use_percent >= critical: - print "CRITICAL: memory (ram) over", use_percent, '%', "used" - sys.exit(CRIT) - elif warning <= use_percent < critical: - print "WARNING: memory (ram) over", use_percent, '%', "used" - sys.exit(WARN) - elif use_percent < warning: - print "OK: memory is only", use_percent, '%', "used" - sys.exit(OK) + # Memory usage calculation + mem_used = total - free + swap_used = swap_total - swap_free + + # Convert from kB to GB for easier interpretation + mem_used_gb = mem_used / 1024 / 1024 + total_gb = total / 1024 / 1024 + swap_used_gb = swap_used / 1024 / 1024 + swap_total_gb = swap_total / 1024 / 1024 + + # Percentage calculation + mem_use_percent = 100 - ((free * 100) / total) + + # Swap percentage calculation. If swap_total is 0, set swap_use_percent to 0 + if swap_total == 0: + swap_use_percent = 0 else: - print ("UNKNOWN: unable to process free memory\n", use_percent) - sys.exit(UNKNOWN) + swap_use_percent = 100 - ((swap_free * 100) / swap_total) + # Performance data with more detail + mem_perf_data = f"mem_used_pc={mem_use_percent}%;{warning};{critical};0;100 " \ + f"mem_used_gb={mem_used_gb:.2f}GB; mem_total_gb={total_gb:.2f}GB" + swap_perf_data = f"swap_used_pc={swap_use_percent}%;{swap_warning};{swap_critical};0;100 " \ + f"swap_used_gb={swap_used_gb:.2f}GB; swap_total_gb={swap_total_gb:.2f}GB" + + # Determine the highest severity status + max_status = OK + messages = [] + + if mem_use_percent >= critical: + messages.append(f"CRITICAL: RAM over {mem_use_percent:.2f}% used") + max_status = CRIT + elif warning <= mem_use_percent < critical: + messages.append(f"WARNING: RAM over {mem_use_percent:.2f}% used") + if max_status < WARN: + max_status = WARN + + if swap_use_percent >= swap_critical: + messages.append(f"CRITICAL: Swap over {swap_use_percent:.2f}% used") + max_status = CRIT + elif swap_warning <= swap_use_percent < swap_critical: + messages.append(f"WARNING: Swap over {swap_use_percent:.2f}% used") + if max_status < WARN: + max_status = WARN + + if not messages: # All is OK + messages.append(f"OK: RAM is {mem_use_percent:.2f}%, Swap is {swap_use_percent:.2f}%") + + # Combine all messages and exit with the highest severity found + final_message = ' | '.join(messages) + print(f"{final_message} | {mem_perf_data} {swap_perf_data}") + sys.exit(max_status) mem_load() +