#!/usr/bin/perl ############################################################################### # Super simple Nagios plugin to check if the amount of free memory is above # a specified percentage. Written 2023-08-23 by Scott Baker from # https://www.perturb.org/ # # Warn if below 50% free, and Critical if below 25%: Example usage # ./check_mem_free --warn 50 --crit 25 ############################################################################### use strict; use warnings; use v5.16; use Getopt::Long; ############################################################################### my $OK = 0; my $WARN = 1; my $CRIT = 2; my $UNKNOWN = 3; # Warn/Crit thresholds. Alarm if free mem percent LESS than these numbers my $warn_th = 50; my $crit_th = 25; # You can check the 'free' or 'available' memory # we probably want available because that includes cache that COULD # be freed up if needed my $check_field = 'available'; # default to available my $debug = 0; GetOptions( 'warn=i' => \$warn_th, 'crit=i' => \$crit_th, 'debug' => \$debug, 'help' => \&help, 'field=s' => \$check_field, ); ############################################################################### if ($debug) { print "Warning threshold : $warn_th\n"; print "Critical threshold: $crit_th\n"; } my $x = get_free_mem_info(); my $bytes = $x->{$check_field}; my $total = $x->{total}; my $size = human_size($bytes); my $percent = sprintf("%0.2f", ($bytes / $total) * 100); if ($debug) { k($x); } if ($percent < $crit_th) { print "CRITICAL - $check_field memory: $percent% ($size)"; exit($CRIT); } elsif ($percent < $warn_th) { print "WARNING - $check_field memory: $percent% ($size)"; exit($WARN); } else { print "OK - $check_field memory: $percent% ($size)"; exit $OK; } ############################################################################## sub help { print "Help: $0 --warn [warn less than XX%] --crit [critical less than YY%]\n"; exit(5); } sub get_free_mem_info { my $cmd = "/usr/bin/free -b"; my @out = `$cmd`; # total used free shared buff/cache available #Mem: 16125900 1367048 13716408 28648 1042444 14435956 #Swap: 3145724 0 3145724 my $line = $out[1] || ""; my @x = split(' ', $line); my $ret = {}; $ret->{total} = $x[1]; $ret->{used} = $x[2]; $ret->{free} = $x[3]; $ret->{shared} = $x[4]; $ret->{cached} = $x[5]; $ret->{available} = $x[6]; return $ret; } sub human_size { my $size = shift(); if (!$size) { return undef; } if ($size >= (1024**5) * 0.98) { $size = sprintf("%.1fPB", $size / 1024**5); } elsif ($size >= (1024**4) * 0.98) { $size = sprintf("%.1fTB", $size / 1024**4); } elsif ($size >= (1024**3) * 0.98) { $size = sprintf("%.1fGB", $size / 1024**3); } elsif ($size >= (1024**2) * 0.98) { $size = sprintf("%.1fMB", $size / 1024**2); } elsif ($size >= 1024) { $size = sprintf("%.1fKB", $size / 1024); } elsif ($size >= 0) { $size = sprintf("%dB" , $size); } return $size; } # Debug print variable using either Data::Dump::Color (preferred) or Data::Dumper # Creates methods k() and kd() to print, and print & die respectively BEGIN { if (eval { require Data::Dump::Color }) { *k = sub { Data::Dump::Color::dd(@_) }; } else { require Data::Dumper; *k = sub { print Data::Dumper::Dumper(\@_) }; } sub kd { k(@_); printf("Died at %2\$s line #%3\$s\n",caller()); exit(15); } } # vim: tabstop=4 shiftwidth=4 noexpandtab autoindent softtabstop=4 filetype=perl