Initial import from http://...
Benjamin Renard authored 13 years ago
|
1) #!/usr/bin/perl -w
2) # Check SMART status of ATA/SCSI disks, returning any usable metrics as perfdata.
3) # For usage information, run ./check_smart -h
4) #
5) # This script was created under contract for the US Government and is therefore Public Domain
6) #
7) # Changes and Modifications
8) # =========================
9) # Feb 3, 2009: Kurt Yoder - initial version of script 1.0
10) # Jan 27, 2010: Philippe Genonceaux - modifications for compatibility with megaraid, use smartmontool version >= 5.39
|
Added 'fork' information in...
Benjamin Renard authored 13 years ago
|
11) # May 13, 2011: Benjamin Renard - "Fork" in a Git repository : http://git.zionetrix.net
|
Initial import from http://...
Benjamin Renard authored 13 years ago
|
12) # Add this line to /etc/sudoers: "nagios ALL=(root) NOPASSWD: /usr/sbin/smartctl"
13)
14) use strict;
15) use Getopt::Long;
16)
17) use File::Basename qw(basename);
18) my $basename = basename($0);
19)
20) my $revision = '$Revision: 1.0.1 $';
21)
22) use lib '/usr/lib/nagios/plugins/';
23) use utils qw(%ERRORS &print_revision &support &usage);
24)
25) $ENV{'PATH'}='/bin:/usr/bin:/sbin:/usr/sbin';
26) $ENV{'BASH_ENV'}='';
27) $ENV{'ENV'}='';
28)
29) use vars qw($opt_d $opt_debug $opt_h $opt_i $opt_n $opt_v);
30) Getopt::Long::Configure('bundling');
31) GetOptions(
32) "debug" => \$opt_debug,
33) "d=s" => \$opt_d, "device=s" => \$opt_d,
34) "h" => \$opt_h, "help" => \$opt_h,
35) "i=s" => \$opt_i, "interface=s" => \$opt_i,
36) "n=s" => \$opt_n, "number=s" => \$opt_n,
37) "v" => \$opt_v, "version" => \$opt_v,
38) );
39)
40) if ($opt_v) {
41) print_revision($basename,$revision);
42) exit $ERRORS{'OK'};
43) }
44)
45) if ($opt_h) {
46) print_help();
47) exit $ERRORS{'OK'};
48) }
|
Added initial value to opti...
Benjamin Renard authored 13 years ago
|
49) my ($device, $interface, $number) = qw/0 0 0/;
|
Initial import from http://...
Benjamin Renard authored 13 years ago
|
50) if ($opt_d) {
51) unless($opt_i){
52) print "must specify an interface for $opt_d using -i/--interface!\n\n";
53) print_help();
54) exit $ERRORS{'UNKNOWN'};
55) }
56)
57) if (-b $opt_d){
58) $device = $opt_d;
59) }
60) else{
61) print "$opt_d is not a valid block device!\n\n";
62) print_help();
63) exit $ERRORS{'UNKNOWN'};
64) }
65)
66) if(grep {$opt_i eq $_} ('ata', 'scsi', 'megaraid')){
67) $interface = $opt_i;
68) if($interface eq 'megaraid'){
69) if(defined($opt_n)){
70) $number = $opt_n;
71) $interface = $opt_i.",".$number;
72) }
73) else{
74) print "must specify a physical disk number within the MegaRAID controller!\n\n";
75) print_help();
76) exit $ERRORS{'UNKNOWN'};
77) }
78) }
79) }
80) else{
81) print "invalid interface $opt_i for $opt_d!\n\n";
82) print_help();
83) exit $ERRORS{'UNKNOWN'};
84) }
85) }
86) else{
87) print "must specify a device!\n\n";
88) print_help();
89) exit $ERRORS{'UNKNOWN'};
90) }
91) my $smart_command = '/usr/bin/sudo /usr/sbin/smartctl';
92) my @error_messages = qw//;
93) my $exit_status = 'OK';
94)
95)
96) warn "###########################################################\n" if $opt_debug;
97) warn "(debug) CHECK 1: getting overall SMART health status\n" if $opt_debug;
98) warn "###########################################################\n\n\n" if $opt_debug;
99)
100) my $full_command = "$smart_command -d $interface -H $device";
101) warn "(debug) executing:\n$full_command\n\n" if $opt_debug;
102)
103) my @output = `$full_command`;
104) warn "(debug) output:\n@output\n\n" if $opt_debug;
105)
106) # parse ata output, looking for "health status: passed"
107) my $found_status = 0;
108) my $line_str = 'SMART overall-health self-assessment test result: '; # ATA SMART line
109) my $ok_str = 'PASSED'; # ATA SMART OK string
110)
|
Fixed error in SMART Health...
Benjamin Renard authored 13 years ago
|
111) if ($interface eq 'megaraid'.",".$number or $interface eq 'scsi'){
|
Initial import from http://...
Benjamin Renard authored 13 years ago
|
112) $line_str = 'SMART Health Status: '; # SCSI OR MEGARAID SMART line
113) $ok_str = 'OK'; #SCSI OR MEGARAID SMART OK string
114) }
115)
116) foreach my $line (@output){
117) if($line =~ /$line_str(.+)/){
118) $found_status = 1;
119) warn "(debug) parsing line:\n$line\n\n" if $opt_debug;
120) if ($1 eq $ok_str) {
121) warn "(debug) found string '$ok_str'; status OK\n\n" if $opt_debug;
122) }
123) else {
124) warn "(debug) no '$ok_str' status; failing\n\n" if $opt_debug;
125) push(@error_messages, "Health status: $1");
126) escalate_status('CRITICAL');
127) }
128) }
129) }
130)
131) unless ($found_status) {
132) push(@error_messages, 'No health status line found');
133) escalate_status('UNKNOWN');
134) }
135)
136)
137) warn "###########################################################\n" if $opt_debug;
138) warn "(debug) CHECK 2: getting silent SMART health check\n" if $opt_debug;
139) warn "###########################################################\n\n\n" if $opt_debug;
140)
141) $full_command = "$smart_command -d $interface -q silent -A $device";
142) warn "(debug) executing:\n$full_command\n\n" if $opt_debug;
143)
144) system($full_command);
145) my $return_code = $?;
146) warn "(debug) exit code:\n$return_code\n\n" if $opt_debug;
147)
148) if ($return_code & 0x01) {
149) push(@error_messages, 'Commandline parse failure');
150) escalate_status('UNKNOWN');
151) }
152) if ($return_code & 0x02) {
153) push(@error_messages, 'Device could not be opened');
154) escalate_status('UNKNOWN');
155) }
156) if ($return_code & 0x04) {
157) push(@error_messages, 'Checksum failure');
158) escalate_status('WARNING');
159) }
160) if ($return_code & 0x08) {
161) push(@error_messages, 'Disk is failing');
162) escalate_status('CRITICAL');
163) }
164) if ($return_code & 0x10) {
165) push(@error_messages, 'Disk is in prefail');
166) escalate_status('WARNING');
167) }
168) if ($return_code & 0x20) {
169) push(@error_messages, 'Disk may be close to failure');
170) escalate_status('WARNING');
171) }
172) if ($return_code & 0x40) {
173) push(@error_messages, 'Error log contains errors');
174) escalate_status('WARNING');
175) }
176) if ($return_code & 0x80) {
177) push(@error_messages, 'Self-test log contains errors');
178) escalate_status('WARNING');
179) }
180) if ($return_code && !$exit_status) {
181) push(@error_messages, 'Unknown return code');
182) escalate_status('CRITICAL');
183) }
184)
185) if ($return_code) {
186) warn "(debug) non-zero exit code, generating error condition\n\n" if $opt_debug;
187) }
188) else {
189) warn "(debug) zero exit code, status OK\n\n" if $opt_debug;
190) }
191)
192)
193) warn "###########################################################\n" if $opt_debug;
194) warn "(debug) CHECK 3: getting detailed statistics\n" if $opt_debug;
195) warn "(debug) information contains a few more potential trouble spots\n" if $opt_debug;
196) warn "(debug) plus, we can also use the information for perfdata/graphing\n" if $opt_debug;
197) warn "###########################################################\n\n\n" if $opt_debug;
198)
199) $full_command = "$smart_command -d $interface -A $device";
200) warn "(debug) executing:\n$full_command\n\n" if $opt_debug;
201) @output = `$full_command`;
202) warn "(debug) output:\n@output\n\n" if $opt_debug;
203) my @perfdata = qw//;
204)
205) # separate metric-gathering and output analysis for ATA vs SCSI SMART output
206) if ($interface eq 'ata'){
207) foreach my $line(@output){
208) # get lines that look like this:
209) # 9 Power_On_Minutes 0x0032 241 241 000 Old_age Always - 113h+12m
210) next unless $line =~ /^\s*\d+\s(\S+)\s+(?:\S+\s+){6}(\S+)\s+(\d+)/;
211) my ($attribute_name, $when_failed, $raw_value) = ($1, $2, $3);
|
Added exception for errors...
Benjamin Renard authored 13 years ago
|
212) if ($when_failed ne '-' && $when_failed ne 'In_the_past'){
|