OSDN Git Service

adds the check_mem.pl plugin support.
[metasearch/grid-chef-repo.git] / cookbooks / nagios-grid / templates / default / usr / lib / nagios / plugins / check_mem.pl
1 #!/usr/bin/perl -w
2
3 # Heavily based on the script from:
4 # check_mem.pl Copyright (C) 2000 Dan Larsson <dl@tyfon.net>
5 # heavily modified by
6 # Justin Ellison <justin@techadvise.com>
7 #
8 # The MIT License (MIT)
9 # Copyright (c) 2011 justin@techadvise.com
10
11 # Permission is hereby granted, free of charge, to any person obtaining a copy of this
12 # software and associated documentation files (the "Software"), to deal in the Software
13 # without restriction, including without limitation the rights to use, copy, modify,
14 # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
15 # permit persons to whom the Software is furnished to do so, subject to the following conditions:
16
17 # The above copyright notice and this permission notice shall be included in all copies
18 # or substantial portions of the Software.
19
20 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21 # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22 # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23 # FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
24 # OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 # OTHER DEALINGS IN THE SOFTWARE.
26
27 # Tell Perl what we need to use
28 use strict;
29 use Getopt::Std;
30
31 #TODO - Convert to Nagios::Plugin
32 #TODO - Use an alarm
33
34 # Predefined exit codes for Nagios
35 use vars qw($opt_c $opt_f $opt_u $opt_w $opt_C $opt_v %exit_codes);
36 %exit_codes   = ('UNKNOWN' , 3,
37                  'OK'      , 0,
38                  'WARNING' , 1,
39                  'CRITICAL', 2,
40                  );
41
42 # Get our variables, do our checking:
43 init();
44
45 # Get the numbers:
46 my ($free_memory_kb,$used_memory_kb,$caches_kb) = get_memory_info();
47 print "$free_memory_kb Free\n$used_memory_kb Used\n$caches_kb Cache\n" if ($opt_v);
48
49 if ($opt_C) { #Do we count caches as free?
50     $used_memory_kb -= $caches_kb;
51     $free_memory_kb += $caches_kb;
52 }
53
54 # Round to the nearest KB
55 $free_memory_kb = sprintf('%d',$free_memory_kb);
56 $used_memory_kb = sprintf('%d',$used_memory_kb);
57 $caches_kb = sprintf('%d',$caches_kb);
58
59 # Tell Nagios what we came up with
60 tell_nagios($used_memory_kb,$free_memory_kb,$caches_kb);
61
62
63 sub tell_nagios {
64     my ($used,$free,$caches) = @_;
65     
66     # Calculate Total Memory
67     my $total = $free + $used;
68     print "$total Total\n" if ($opt_v);
69
70     my $perf_warn;
71     my $perf_crit;
72     if ( $opt_u ) {
73       $perf_warn = int(${total} * $opt_w / 100);
74       $perf_crit = int(${total} * $opt_c / 100);
75     } else {
76       $perf_warn = int(${total} * ( 100 - $opt_w ) / 100);
77       $perf_crit = int(${total} * ( 100 - $opt_c ) / 100);
78     }
79     
80     my $perfdata = "|TOTAL=${total}KB;;;; USED=${used}KB;${perf_warn};${perf_crit};; FREE=${free}KB;;;; CACHES=${caches}KB;;;;";
81
82     if ($opt_f) {
83       my $percent    = sprintf "%.1f", ($free / $total * 100);
84       if ($percent <= $opt_c) {
85           finish("CRITICAL - $percent% ($free kB) free!$perfdata",$exit_codes{'CRITICAL'});
86       }
87       elsif ($percent <= $opt_w) {
88           finish("WARNING - $percent% ($free kB) free!$perfdata",$exit_codes{'WARNING'});
89       }
90       else {
91           finish("OK - $percent% ($free kB) free.$perfdata",$exit_codes{'OK'});
92       }
93     }
94     elsif ($opt_u) {
95       my $percent    = sprintf "%.1f", ($used / $total * 100);
96       if ($percent >= $opt_c) {
97           finish("CRITICAL - $percent% ($used kB) used!$perfdata",$exit_codes{'CRITICAL'});
98       }
99       elsif ($percent >= $opt_w) {
100           finish("WARNING - $percent% ($used kB) used!$perfdata",$exit_codes{'WARNING'});
101       }
102       else {
103           finish("OK - $percent% ($used kB) used.$perfdata",$exit_codes{'OK'});
104       }
105     }
106 }
107
108 # Show usage
109 sub usage() {
110   print "\ncheck_mem.pl v1.0 - Nagios Plugin\n\n";
111   print "usage:\n";
112   print " check_mem.pl -<f|u> -w <warnlevel> -c <critlevel>\n\n";
113   print "options:\n";
114   print " -f           Check FREE memory\n";
115   print " -u           Check USED memory\n";
116   print " -C           Count OS caches as FREE memory\n";
117   print " -w PERCENT   Percent free/used when to warn\n";
118   print " -c PERCENT   Percent free/used when critical\n";
119   print "\nCopyright (C) 2000 Dan Larsson <dl\@tyfon.net>\n";
120   print "check_mem.pl comes with absolutely NO WARRANTY either implied or explicit\n";
121   print "This program is licensed under the terms of the\n";
122   print "MIT License (check source code for details)\n";
123   exit $exit_codes{'UNKNOWN'}; 
124 }
125
126 sub get_memory_info {
127     my $used_memory_kb  = 0;
128     my $free_memory_kb  = 0;
129     my $total_memory_kb = 0;
130     my $caches_kb       = 0;
131
132     my $uname;
133     if ( -e '/usr/bin/uname') {
134         $uname = `/usr/bin/uname -a`;
135     }
136     elsif ( -e '/bin/uname') {
137         $uname = `/bin/uname -a`;
138     }
139     else {
140         die "Unable to find uname in /usr/bin or /bin!\n";
141     }
142     print "uname returns $uname" if ($opt_v);
143     if ( $uname =~ /Linux/ ) {
144         my @meminfo = `/bin/cat /proc/meminfo`;
145         foreach (@meminfo) {
146             chomp;
147             if (/^Mem(Total|Free):\s+(\d+) kB/) {
148                 my $counter_name = $1;
149                 if ($counter_name eq 'Free') {
150                     $free_memory_kb = $2;
151                 }
152                 elsif ($counter_name eq 'Total') {
153                     $total_memory_kb = $2;
154                 }
155             }
156             elsif (/^(Buffers|Cached|SReclaimable):\s+(\d+) kB/) {
157                 $caches_kb += $2;
158             }
159             elsif (/^Shmem:\s+(\d+) kB/) {
160                 $caches_kb -= $1;
161             }
162         }
163         $used_memory_kb = $total_memory_kb - $free_memory_kb;
164     }
165     elsif ( $uname =~ /HP-UX/ ) {
166       # HP-UX, thanks to Christoph Fürstaller
167       my @meminfo = `/usr/bin/sudo /usr/local/bin/kmeminfo`;
168       foreach (@meminfo) {
169         chomp;
170         if (/^Physical memory\s\s+=\s+(\d+)\s+(\d+.\d)g/) {
171           $total_memory_kb = ($2 * 1024 * 1024);
172         }
173         elsif (/^Free memory\s\s+=\s+(\d+)\s+(\d+.\d)g/) {
174           $free_memory_kb = ($2 * 1024 * 1024);
175         }
176       }
177      $used_memory_kb = $total_memory_kb - $free_memory_kb;
178     }
179     elsif ( $uname =~ /FreeBSD/ ) {
180       # The FreeBSD case. 2013-03-19 www.claudiokuenzler.com
181       # free mem = Inactive*Page Size + Cache*Page Size + Free*Page Size
182       my $pagesize = `sysctl vm.stats.vm.v_page_size`;
183       $pagesize =~ s/[^0-9]//g;
184       my $mem_inactive = 0;
185       my $mem_cache = 0;
186       my $mem_free = 0;
187       my $mem_total = 0;
188       my $free_memory = 0;
189         my @meminfo = `/sbin/sysctl vm.stats.vm`;
190         foreach (@meminfo) {
191             chomp;
192             if (/^vm.stats.vm.v_inactive_count:\s+(\d+)/) {
193             $mem_inactive = ($1 * $pagesize);
194             }
195             elsif (/^vm.stats.vm.v_cache_count:\s+(\d+)/) {
196             $mem_cache = ($1 * $pagesize);
197             }
198             elsif (/^vm.stats.vm.v_free_count:\s+(\d+)/) {
199             $mem_free = ($1 * $pagesize);
200             }
201             elsif (/^vm.stats.vm.v_page_count:\s+(\d+)/) {
202             $mem_total = ($1 * $pagesize);
203             }
204         }
205         $free_memory = $mem_inactive + $mem_cache + $mem_free;
206         $free_memory_kb = ( $free_memory / 1024);
207         $total_memory_kb = ( $mem_total / 1024);
208         $used_memory_kb = $total_memory_kb - $free_memory_kb;
209         $caches_kb = ($mem_cache / 1024);
210     }
211     elsif ( $uname =~ /joyent/ ) {
212       # The SmartOS case. 2014-01-10 www.claudiokuenzler.com
213       # free mem = pagesfree * pagesize
214       my $pagesize = `pagesize`;
215       my $phys_pages = `kstat -p unix:0:system_pages:pagestotal | awk '{print \$NF}'`;
216       my $free_pages = `kstat -p unix:0:system_pages:pagesfree | awk '{print \$NF}'`;
217       my $arc_size = `kstat -p zfs:0:arcstats:size | awk '{print \$NF}'`;
218       my $arc_size_kb = $arc_size / 1024;
219
220       print "Pagesize is $pagesize" if ($opt_v);
221       print "Total pages is $phys_pages" if ($opt_v);
222       print "Free pages is $free_pages" if ($opt_v);
223       print "Arc size is $arc_size" if ($opt_v);
224
225       $caches_kb += $arc_size_kb;
226
227       $total_memory_kb = $phys_pages * $pagesize / 1024;
228       $free_memory_kb = $free_pages * $pagesize / 1024;
229       $used_memory_kb = $total_memory_kb - $free_memory_kb;
230     }
231     elsif ( $uname =~ /SunOS/ ) {
232         eval "use Sun::Solaris::Kstat";
233         if ($@) { #Kstat not available
234             if ($opt_C) {
235                 print "You can't report on Solaris caches without Sun::Solaris::Kstat available!\n";
236                 exit $exit_codes{UNKNOWN};
237             }
238             my @vmstat = `/usr/bin/vmstat 1 2`;
239             my $line;
240             foreach (@vmstat) {
241               chomp;
242               $line = $_;
243             }
244             $free_memory_kb = (split(/ /,$line))[5] / 1024;
245             my @prtconf = `/usr/sbin/prtconf`;
246             foreach (@prtconf) {
247                 if (/^Memory size: (\d+) Megabytes/) {
248                     $total_memory_kb = $1 * 1024;
249                 }
250             }
251             $used_memory_kb = $total_memory_kb - $free_memory_kb;
252             
253         }
254         else { # We have kstat
255             my $kstat = Sun::Solaris::Kstat->new();
256             my $phys_pages = ${kstat}->{unix}->{0}->{system_pages}->{physmem};
257             my $free_pages = ${kstat}->{unix}->{0}->{system_pages}->{freemem};
258             # We probably should account for UFS caching here, but it's unclear
259             # to me how to determine UFS's cache size.  There's inode_cache,
260             # and maybe the physmem variable in the system_pages module??
261             # In the real world, it looks to be so small as not to really matter,
262             # so we don't grab it.  If someone can give me code that does this, 
263             # I'd be glad to put it in.
264             my $arc_size = (exists ${kstat}->{zfs} && ${kstat}->{zfs}->{0}->{arcstats}->{size}) ?
265                  ${kstat}->{zfs}->{0}->{arcstats}->{size} / 1024 
266                  : 0;
267             $caches_kb += $arc_size;
268             my $pagesize = `pagesize`;
269     
270             $total_memory_kb = $phys_pages * $pagesize / 1024;
271             $free_memory_kb = $free_pages * $pagesize / 1024;
272             $used_memory_kb = $total_memory_kb - $free_memory_kb;
273         }
274     }
275     elsif ( $uname =~ /Darwin/ ) {
276         $total_memory_kb = (split(/ /,`/usr/sbin/sysctl hw.memsize`))[1]/1024;
277         my $pagesize     = (split(/ /,`/usr/sbin/sysctl hw.pagesize`))[1];
278         $caches_kb       = 0;
279         my @vm_stat = `/usr/bin/vm_stat`;
280         foreach (@vm_stat) {
281             chomp;
282             if (/^(Pages free):\s+(\d+)\.$/) {
283                 $free_memory_kb = $2*$pagesize/1024;
284             }
285             # 'caching' concept works different on MACH
286             # this should be a reasonable approximation
287             elsif (/^Pages (inactive|purgable):\s+(\d+).$/) {
288                 $caches_kb += $2*$pagesize/1024;
289             }
290         }
291         $used_memory_kb = $total_memory_kb - $free_memory_kb;
292     }
293     elsif ( $uname =~ /AIX/ ) {
294         my @meminfo = `/usr/bin/vmstat -vh`;
295         foreach (@meminfo) {
296             chomp;
297             if (/^\s*([0-9.]+)\s+(.*)/) {
298                 my $counter_name = $2;
299                 if ($counter_name eq 'memory pages') {
300                     $total_memory_kb = $1*4;
301                 }
302                 if ($counter_name eq 'free pages') {
303                     $free_memory_kb = $1*4;
304                 }
305                 if ($counter_name eq 'file pages') {
306                     $caches_kb = $1*4;
307                 }
308                 if ($counter_name eq 'Number of 4k page frames loaned') {
309                     $free_memory_kb += $1*4;
310                 }
311             }
312         }
313         $used_memory_kb = $total_memory_kb - $free_memory_kb;
314     }
315     else {
316         if ($opt_C) {
317             print "You can't report on $uname caches!\n";
318             exit $exit_codes{UNKNOWN};
319         }
320         my $command_line = `vmstat | tail -1 | awk '{print \$4,\$5}'`;
321         chomp $command_line;
322         my @memlist      = split(/ /, $command_line);
323     
324         # Define the calculating scalars
325         $used_memory_kb  = $memlist[0]/1024;
326         $free_memory_kb = $memlist[1]/1024;
327         $total_memory_kb = $used_memory_kb + $free_memory_kb;
328     }
329     return ($free_memory_kb,$used_memory_kb,$caches_kb);
330 }
331
332 sub init {
333     # Get the options
334     if ($#ARGV le 0) {
335       &usage;
336     }
337     else {
338       getopts('c:fuCvw:');
339     }
340     
341     # Shortcircuit the switches
342     if (!$opt_w or $opt_w == 0 or !$opt_c or $opt_c == 0) {
343       print "*** You must define WARN and CRITICAL levels!\n";
344       &usage;
345     }
346     elsif (!$opt_f and !$opt_u) {
347       print "*** You must select to monitor either USED or FREE memory!\n";
348       &usage;
349     }
350     
351     # Check if levels are sane
352     if ($opt_w <= $opt_c and $opt_f) {
353       print "*** WARN level must not be less than CRITICAL when checking FREE memory!\n";
354       &usage;
355     }
356     elsif ($opt_w >= $opt_c and $opt_u) {
357       print "*** WARN level must not be greater than CRITICAL when checking USED memory!\n";
358       &usage;
359     }
360 }
361
362 sub finish {
363     my ($msg,$state) = @_;
364     print "$msg\n";
365     exit $state;
366 }