--- /dev/null
+# $Id#
+# vim:syn=perl:expandtab:ts=3:sw=3:ai:si
+# Register this routine with the plugin registry
+$CHECKFUNCS{'memory'} = \&check_memory;
+
+# This routine checks the memory usage on various systems. Since I can't find a
+# nice way of doing things, we grab the output of top or free on linux. It's
+# likely going to have to be configured for each OS it runs on. :-(
+
+# $MEMCHECK = "/usr/bin/top -b -n 1 "; # To use 'top'
+# $MEMCHECK = "/usr/bin/free"; # On linux systems
+
+sub check_memory {
+ if (!defined $MEMWARN or !defined $MEMCRIT) {
+ $color = "yellow";
+ $summary = "Warning levels not defined";
+ $message = "\$MEMWARN or \$MEMCRIT not defined!";
+ } elsif ($MEMCHECK =~ /free/) {
+ ($color, $summary, $message) = &check_memory_free;
+ } elsif ($MEMCHECK =~ /top/) {
+ ($color, $summary, $message) = &check_memory_top;
+ } else {
+ $color = "yellow";
+ $summary = "Don't know how to check memory";
+ $message = "No suitable memory-checking command found\n".
+ "\$MEMCHECK=\"$MEMCHECK\"";
+ }
+
+ &debug( "memory - $color, $summary" );
+ &status( $SPONGSERVER, $HOST, "memory", $color, $summary, $message );
+}
+
+sub check_memory_free {
+ open CMD, "$MEMCHECK |";
+ $message = <CMD>;
+
+ $line = <CMD>;
+ ($memtotal, $memused, $memfree, $shared, $buffers, $cached) =
+ ( $line =~ /^Mem:\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/ );
+ $message .= $line;
+
+ $line = <CMD>;
+ ($hardmemused, $hardmemfree) =
+ ( $line =~ /^[^:]*:\s+(\d+)\s+(\d+)/ );
+ $message .= $line;
+
+ $line = <CMD>;
+ ($swaptotal, $swapused, $swapfree) =
+ ( $line =~ /^Swap:\s+(\d+)\s+(\d+)\s+(\d+)/ );
+ $message .= $line;
+
+ $physpctused = floor($hardmemused/$memtotal*100);
+ $virtpctused = floor(($hardmemused+$swapused)/($memtotal+$swaptotal)*100);
+ $summary = "$physpctused% phys mem used, $virtpctused% virt mem used";
+
+ $color = "green";
+ if ($virtpctused > $MEMWARN) { $color = "yellow"; }
+ if ($virtpctused > $MEMCRIT) { $color = "red"; }
+
+ close CMD;
+ return ($color, $summary, $message);
+}
+
+sub check_memory_top {
+ $kmb='\s+(\d+[KM])';
+ @parse_error = ("yellow", "Can't parse memory line", $message);
+ open CMD, "$MEMCHECK |";
+ while (<CMD>) {
+ /PID/ && last;
+ /^$/ && next;
+ $message .= $_;
+ if (/^Mem/) {
+ # top from the procps on Linux has this format:
+ if (/^Mem:$kmb av,$kmb used,$kmb free,$kmb shrd,$kmb buff/) {
+ ($memtotal,$memused,$memfree,$shared,$buffers) = ($1,$2,$3,$4,$5);
+ &to_KB($memtotal,$memused,$memfree,$shared,$buffers);
+ $_ = <CMD>;
+ $message .= $_;
+ if (/^Swap:$kmb av,$kmb used,$kmb free$kmb cached/) {
+ ($swaptotal, $swapused, $swapfree, $cached) = ($1,$2,$3,$4);
+ &to_KB($swaptotal, $swapused, $swapfree, $cached);
+ } else {
+ close CMD;
+ return @parse_error;
+ };
+ $hardmemused = $memused-$buffers-$cached;
+ } elsif (/^Memory:$kmb real,$kmb free,$kmb swap,$kmb free swap/) {
+ # the top package supporting various unices has this format
+ ($memtotal,$memfree,$swapused,$swapfree) = ($1,$2,$3,$4);
+ &to_KB($memtotal,$memfree,$swapused,$swapfree);
+ $hardmemused = $memtotal-$memfree;
+ $swaptotal = $swapused+$swapfree;
+ } elsif (/^Memory:$kmb real,$kmb free,$kmb swap in use,$kmb swap free/) {
+ # the top package supporting various unices has this format
+ ($memtotal,$memfree,$swapused,$swapfree) = ($1,$2,$3,$4);
+ &to_KB($memtotal,$memfree,$swapused,$swapfree);
+ $hardmemused = $memtotal-$memfree;
+ $swaptotal = $swapused+$swapfree;
+ } else {
+ close CMD;
+ return @parse_error;
+ }
+ $physpctused = floor($hardmemused/$memtotal*100);
+ $virtpctused = floor(($hardmemused+$swapused)/($memtotal+$swaptotal)*100);
+ }
+ }
+ close CMD;
+ $color = "green";
+ $summary = "$physpctused% phys mem used, $virtpctused% virt mem used";
+ if ($virtpctused > $MEMWARN) { $color = "yellow"; }
+ if ($virtpctused > $MEMCRIT) { $color = "red"; }
+ return ($color, $summary, $message);
+}
+
+# Convert each value to the appropriate number of kilobytes
+sub to_KB {
+ my $i;
+ for ($i=0; $i <= (scalar(@_)-1); ++$i) {
+ if ($_[$i] =~ /^(\d+)$/) { $_[$i] = floor($1/1024); next; }
+ if ($_[$i] =~ /^(\d+)K$/) { $_[$i] = $1; next; }
+ if ($_[$i] =~ /^(\d+)M$/) { $_[$i] = floor($1*1024); next; }
+ }
+ return @_;
+}
+
+# I'm included perl code, I need this.
+1;