~charm-demo/charms/trusty/nrpe/trunk

« back to all changes in this revision

Viewing changes to plugins/check_mem.pl

  • Committer: Clint Byrum
  • Date: 2012-07-13 18:59:03 UTC
  • Revision ID: clint@ubuntu.com-20120713185903-witvmygow4n3n2u4
new plugin for checking memory

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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' ,-1,
 
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 $perfdata = "|TOTAL=${total}KB;;;; USED=${used}KB;;;; FREE=${free}KB;;;; CACHES=${caches}KB;;;;";
 
71
    
 
72
    if ($opt_f) {
 
73
      my $percent    = sprintf "%.1f", ($free / $total * 100);
 
74
      if ($percent <= $opt_c) {
 
75
          finish("CRITICAL - $percent% ($free kB) free!$perfdata",$exit_codes{'CRITICAL'});
 
76
      }
 
77
      elsif ($percent <= $opt_w) {
 
78
          finish("WARNING - $percent% ($free kB) free!$perfdata",$exit_codes{'WARNING'});
 
79
      }
 
80
      else {
 
81
          finish("OK - $percent% ($free kB) free.$perfdata",$exit_codes{'OK'});
 
82
      }
 
83
    }
 
84
    elsif ($opt_u) {
 
85
      my $percent    = sprintf "%.1f", ($used / $total * 100);
 
86
      if ($percent >= $opt_c) {
 
87
          finish("CRITICAL - $percent% ($used kB) used!$perfdata",$exit_codes{'CRITICAL'});
 
88
      }
 
89
      elsif ($percent >= $opt_w) {
 
90
          finish("WARNING - $percent% ($used kB) used!$perfdata",$exit_codes{'WARNING'});
 
91
      }
 
92
      else {
 
93
          finish("OK - $percent% ($used kB) used.$perfdata",$exit_codes{'OK'});
 
94
      }
 
95
    }
 
96
}
 
97
 
 
98
# Show usage
 
99
sub usage() {
 
100
  print "\ncheck_mem.pl v1.0 - Nagios Plugin\n\n";
 
101
  print "usage:\n";
 
102
  print " check_mem.pl -<f|u> -w <warnlevel> -c <critlevel>\n\n";
 
103
  print "options:\n";
 
104
  print " -f           Check FREE memory\n";
 
105
  print " -u           Check USED memory\n";
 
106
  print " -C           Count OS caches as FREE memory\n";
 
107
  print " -w PERCENT   Percent free/used when to warn\n";
 
108
  print " -c PERCENT   Percent free/used when critical\n";
 
109
  print "\nCopyright (C) 2000 Dan Larsson <dl\@tyfon.net>\n";
 
110
  print "check_mem.pl comes with absolutely NO WARRANTY either implied or explicit\n";
 
111
  print "This program is licensed under the terms of the\n";
 
112
  print "MIT License (check source code for details)\n";
 
113
  exit $exit_codes{'UNKNOWN'}; 
 
114
}
 
115
 
 
116
sub get_memory_info {
 
117
    my $used_memory_kb  = 0;
 
118
    my $free_memory_kb  = 0;
 
119
    my $total_memory_kb = 0;
 
120
    my $caches_kb       = 0;
 
121
 
 
122
    my $uname;
 
123
    if ( -e '/usr/bin/uname') {
 
124
        $uname = `/usr/bin/uname -a`;
 
125
    }
 
126
    elsif ( -e '/bin/uname') {
 
127
        $uname = `/bin/uname -a`;
 
128
    }
 
129
    else {
 
130
        die "Unable to find uname in /usr/bin or /bin!\n";
 
131
    }
 
132
    print "uname returns $uname" if ($opt_v);
 
133
    if ( $uname =~ /Linux/ ) {
 
134
        my @meminfo = `/bin/cat /proc/meminfo`;
 
135
        foreach (@meminfo) {
 
136
            chomp;
 
137
            if (/^Mem(Total|Free):\s+(\d+) kB/) {
 
138
                my $counter_name = $1;
 
139
                if ($counter_name eq 'Free') {
 
140
                    $free_memory_kb = $2;
 
141
                }
 
142
                elsif ($counter_name eq 'Total') {
 
143
                    $total_memory_kb = $2;
 
144
                }
 
145
            }
 
146
            elsif (/^(Buffers|Cached|SReclaimable):\s+(\d+) kB/) {
 
147
                $caches_kb += $2;
 
148
            }
 
149
        }
 
150
        $used_memory_kb = $total_memory_kb - $free_memory_kb;
 
151
    }
 
152
    elsif ( $uname =~ /SunOS/ ) {
 
153
        eval "use Sun::Solaris::Kstat";
 
154
        if ($@) { #Kstat not available
 
155
            if ($opt_C) {
 
156
                print "You can't report on Solaris caches without Sun::Solaris::Kstat available!\n";
 
157
                exit $exit_codes{UNKNOWN};
 
158
            }
 
159
            my @vmstat = `/usr/bin/vmstat 1 2`;
 
160
            my $line;
 
161
            foreach (@vmstat) {
 
162
              chomp;
 
163
              $line = $_;
 
164
            }
 
165
            $free_memory_kb = (split(/ /,$line))[5] / 1024;
 
166
            my @prtconf = `/usr/sbin/prtconf`;
 
167
            foreach (@prtconf) {
 
168
                if (/^Memory size: (\d+) Megabytes/) {
 
169
                    $total_memory_kb = $1 * 1024;
 
170
                }
 
171
            }
 
172
            $used_memory_kb = $total_memory_kb - $free_memory_kb;
 
173
            
 
174
        }
 
175
        else { # We have kstat
 
176
            my $kstat = Sun::Solaris::Kstat->new();
 
177
            my $phys_pages = ${kstat}->{unix}->{0}->{system_pages}->{physmem};
 
178
            my $free_pages = ${kstat}->{unix}->{0}->{system_pages}->{freemem};
 
179
            # We probably should account for UFS caching here, but it's unclear
 
180
            # to me how to determine UFS's cache size.  There's inode_cache,
 
181
            # and maybe the physmem variable in the system_pages module??
 
182
            # In the real world, it looks to be so small as not to really matter,
 
183
            # so we don't grab it.  If someone can give me code that does this, 
 
184
            # I'd be glad to put it in.
 
185
            my $arc_size = (exists ${kstat}->{zfs} && ${kstat}->{zfs}->{0}->{arcstats}->{size}) ?
 
186
                 ${kstat}->{zfs}->{0}->{arcstats}->{size} / 1024 
 
187
                 : 0;
 
188
            $caches_kb += $arc_size;
 
189
            my $pagesize = `pagesize`;
 
190
    
 
191
            $total_memory_kb = $phys_pages * $pagesize / 1024;
 
192
            $free_memory_kb = $free_pages * $pagesize / 1024;
 
193
            $used_memory_kb = $total_memory_kb - $free_memory_kb;
 
194
        }
 
195
    }
 
196
    elsif ( $uname =~ /AIX/ ) {
 
197
        my @meminfo = `/usr/bin/vmstat -v`;
 
198
        foreach (@meminfo) {
 
199
            chomp;
 
200
            if (/^\s*([0-9.]+)\s+(.*)/) {
 
201
                my $counter_name = $2;
 
202
                if ($counter_name eq 'memory pages') {
 
203
                    $total_memory_kb = $1*4;
 
204
                }
 
205
                if ($counter_name eq 'free pages') {
 
206
                    $free_memory_kb = $1*4;
 
207
                }
 
208
                if ($counter_name eq 'file pages') {
 
209
                    $caches_kb = $1*4;
 
210
                }
 
211
            }
 
212
        }
 
213
        $used_memory_kb = $total_memory_kb - $free_memory_kb;
 
214
    }
 
215
    else {
 
216
        if ($opt_C) {
 
217
            print "You can't report on $uname caches!\n";
 
218
            exit $exit_codes{UNKNOWN};
 
219
        }
 
220
        my $command_line = `vmstat | tail -1 | awk '{print \$4,\$5}'`;
 
221
        chomp $command_line;
 
222
        my @memlist      = split(/ /, $command_line);
 
223
    
 
224
        # Define the calculating scalars
 
225
        $used_memory_kb  = $memlist[0]/1024;
 
226
        $free_memory_kb = $memlist[1]/1024;
 
227
        $total_memory_kb = $used_memory_kb + $free_memory_kb;
 
228
    }
 
229
    return ($free_memory_kb,$used_memory_kb,$caches_kb);
 
230
}
 
231
 
 
232
sub init {
 
233
    # Get the options
 
234
    if ($#ARGV le 0) {
 
235
      &usage;
 
236
    }
 
237
    else {
 
238
      getopts('c:fuCvw:');
 
239
    }
 
240
    
 
241
    # Shortcircuit the switches
 
242
    if (!$opt_w or $opt_w == 0 or !$opt_c or $opt_c == 0) {
 
243
      print "*** You must define WARN and CRITICAL levels!\n";
 
244
      &usage;
 
245
    }
 
246
    elsif (!$opt_f and !$opt_u) {
 
247
      print "*** You must select to monitor either USED or FREE memory!\n";
 
248
      &usage;
 
249
    }
 
250
    
 
251
    # Check if levels are sane
 
252
    if ($opt_w <= $opt_c and $opt_f) {
 
253
      print "*** WARN level must not be less than CRITICAL when checking FREE memory!\n";
 
254
      &usage;
 
255
    }
 
256
    elsif ($opt_w >= $opt_c and $opt_u) {
 
257
      print "*** WARN level must not be greater than CRITICAL when checking USED memory!\n";
 
258
      &usage;
 
259
    }
 
260
}
 
261
 
 
262
sub finish {
 
263
    my ($msg,$state) = @_;
 
264
    print "$msg\n";
 
265
    exit $state;
 
266
}