#!/usr/bin/perl # # check_memory - Check free(1) data against given tresholds # # Copyright (C) 2007 Thomas Guyot-Sionnest # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # use strict; use warnings; use vars qw($PROGNAME $VERSION $FREECMD $UNIT); use Nagios::Plugin; $PROGNAME = "check_memory"; $VERSION = '1.0.1'; $FREECMD = '/usr/bin/free'; $UNIT = 'M'; my $np = Nagios::Plugin->new( usage => "Usage: %s [ -w ] [ -c ]\n" . ' [ -u ]', version => $VERSION, plugin => $PROGNAME, blurb => 'Check free(1) data against given tresholds', timeout => 30, ); $np->add_arg( spec => 'warning|w=s', help => "-w, --warning=THRESHOLD[%]\n" . " Warning threshold (in bytes or percent) for free memory. See\n" . " http://nagiosplug.sourceforge.net/developer-guidelines.html#THRESHOLDFORMAT\n" . " for the threshold format. Alternatively this can be defined as a percentage\n" . ' of minimum free memory (warning and critical must be in the same format).', required => 0, ); $np->add_arg( spec => 'critical|c=s', help => "-c, --critical=THRESHOLD[%]\n" . " Critical threshold (in bytes or percent) for free memory. See\n" . " http://nagiosplug.sourceforge.net/developer-guidelines.html#THRESHOLDFORMAT\n" . " for the threshold format. Alternatively this can be defined as a percentage\n" . ' of minimum free memory (warning and critical must be in the same format).', required => 0, ); $np->add_arg( spec => 'unit|u=s', help => "-u, --unit=UNIT\n" . " Unit to use for human-redeable output. Can be 'b', 'K' 'M' or 'G' for\n" . " bytes, KiB, MiB or GiB respectively (default: '$UNIT').", default => $UNIT, required => 0, ); $np->getopts; # Assign, then check args my $multiple; my $unit = $np->opts->unit; if ($unit eq 'M') { $multiple = 1024 * 1024; } elsif ( $unit eq 'K') { $multiple = 1024; } elsif ( $unit eq 'b') { $multiple = 1; } elsif ( $unit eq 'G') { $multiple = 1024 * 1024 * 1024; } else { $np->nagios_exit('UNKNOWN', "Unit must be one of 'b', 'K', 'M' or 'G', case-sensitive."); } my $verbose = $np->opts->verbose; # Would better fit later but doing it here validates thresholds my $warning = $np->opts->warning; my $critical = $np->opts->critical; $np->set_thresholds( warning => ((defined($warning) && $warning !~ /^\d+%$/) ? $warning : undef), critical => ((defined($critical) && $critical !~ /^\d+%$/) ? $critical : undef), ); # Better safe than sorry alarm $np->opts->timeout; # We always get bytes, then calculate units ourselves warn("Running: '$FREECMD -b'\n") if ($verbose); open(RESULT, "$FREECMD -b |") or $np->nagios_exit('CRITICAL', "Could not run $FREECMD"); warn("Output from $FREECMD:\n") if ($verbose > 1); my $new_format = 0; my ($total, $used, $free); while () { warn(" $_") if ($verbose > 1); # New `free` output from procps doesn't provide "buffers/cache" anymore, but # provides a better estimate of available memory ("available" column). $new_format = 1 if m{^\s+total\s+used\s+free\s+shared\s+buff/cache\s+available$}; if ($new_format and /^Mem:\s+(\d+)\s+\d+\s+\d+\s+\d+\s+\d+\s+(\d+)$/) { $total = $1; $free = $2; # available column $used = $total - $free; # used is everything which is not available } elsif (m#^\-/\+\ buffers/cache:\s*(\d+)\s+(\d+)#) { $used = $1; $free = $2; $total = $used + $free; } } close(RESULT); alarm(0); $np->nagios_exit('CRITICAL', "Unable to interpret $FREECMD output") if (!defined($free)); if (defined($warning) && $warning =~ /^\d+%$/) { if ($warning) { $warning =~ s/%//; $warning = $total / 100 * $warning; $warning .= ':'; } warn("Calculated threshold (from percentage): warn=>$warning\n") if ($verbose); } if (defined($critical) && $critical =~ /^\d+%$/) { if ($critical) { $critical =~ s/%//; $critical = $total / 100 * $critical; $critical .= ':'; } warn("Calculated threshold (from percentage): crit=>$critical\n") if ($verbose); } $np->set_thresholds( warning => $warning, critical => $critical, ); $np->add_perfdata( label => "free", value => $free, uom => 'b', threshold => $np->threshold, ); my $freeprint = int($free/$multiple); $np->nagios_exit($np->check_threshold($free), "$freeprint$unit free");