1 /*****************************************************************************
3 * Nagios check_ide_smart plugin
4 * ide-smart 1.3 - IDE S.M.A.R.T. checking tool
7 * Copyright (C) 1998-1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>
8 * 1998 Gadi Oxman <gadio@netvision.net.il>
9 * Copyright (c) 2000 Robert Dale <rdale@digital-mission.com>
10 * Copyright (c) 2000-2007 Nagios Plugins Development Team
12 * Last Modified: $Date$
16 * This file contains the check_ide_smart plugin
18 * This plugin checks a local hard drive with the (Linux specific) SMART
22 * This program is free software: you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation, either version 3 of the License, or
25 * (at your option) any later version.
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
32 * You should have received a copy of the GNU General Public License
33 * along with this program. If not, see <http://www.gnu.org/licenses/>.
37 *****************************************************************************/
39 const char *progname
= "check_ide_smart";
40 const char *revision
= "$Revision$";
41 const char *copyright
= "1998-2007";
42 const char *email
= "nagiosplug-devel@lists.sourceforge.net";
47 void print_help (void);
48 void print_usage (void);
51 #include <sys/ioctl.h>
53 #include <linux/hdreg.h>
54 #include <linux/types.h>
57 #define NR_ATTRIBUTES 30
68 typedef struct threshold_s
74 __attribute__ ((packed
)) threshold_t
;
76 typedef struct thresholds_s
79 threshold_t thresholds
[NR_ATTRIBUTES
];
84 __attribute__ ((packed
)) thresholds_t
;
86 typedef struct value_s
93 __attribute__ ((packed
)) value_t
;
95 typedef struct values_s
98 value_t values
[NR_ATTRIBUTES
];
101 __u16 offline_timeout
;
103 __u8 offline_capability
;
104 __u16 smart_capability
;
109 __attribute__ ((packed
)) values_t
;
117 offline_status_text
[] =
119 {0x00, "NeverStarted"},
135 {SMART_ENABLE
, "SMART_ENABLE"},
136 {SMART_DISABLE
, "SMART_DISABLE"},
137 {SMART_IMMEDIATE_OFFLINE
, "SMART_IMMEDIATE_OFFLINE"},
138 {SMART_AUTO_OFFLINE
, "SMART_AUTO_OFFLINE"}
142 /* Index to smart_command table, keep in order */
146 SMART_CMD_IMMEDIATE_OFFLINE
,
147 SMART_CMD_AUTO_OFFLINE
150 void print_values (values_t
* p
, thresholds_t
* t
);
151 int smart_cmd_simple (int fd
, enum SmartCommand command
, __u8 val0
, char show_error
);
154 main (int argc
, char *argv
[])
161 thresholds_t thresholds
;
165 /* Parse extra opts if any */
166 argv
=np_extra_opts (&argc
, argv
, progname
);
168 static struct option longopts
[] = {
169 {"device", required_argument
, 0, 'd'},
170 {"immediate", no_argument
, 0, 'i'},
171 {"quiet-check", no_argument
, 0, 'q'},
172 {"auto-on", no_argument
, 0, '1'},
173 {"auto-off", no_argument
, 0, '0'},
174 {"nagios", no_argument
, 0, 'n'},
175 {"help", no_argument
, 0, 'h'},
176 {"version", no_argument
, 0, 'V'}, {0, 0, 0, 0}
179 setlocale (LC_ALL
, "");
180 bindtextdomain (PACKAGE
, LOCALEDIR
);
181 textdomain (PACKAGE
);
185 o
= getopt_long (argc
, argv
, "+d:iq10nhV", longopts
, &longindex
);
187 if (o
== -1 || o
== EOF
|| o
== 1)
213 print_revision (progname
, revision
);
221 device
= argv
[optind
];
229 fd
= open (device
, O_RDONLY
);
232 printf (_("CRITICAL - Couldn't open device %s: %s\n"), device
, strerror (errno
));
233 return STATE_CRITICAL
;
236 if (smart_cmd_simple (fd
, SMART_CMD_ENABLE
, 0, TRUE
)) {
237 printf (_("CRITICAL - SMART_CMD_ENABLE\n"));
238 return STATE_CRITICAL
;
243 retval
= smart_cmd_simple (fd
, SMART_CMD_AUTO_OFFLINE
, 0, TRUE
);
246 retval
= smart_cmd_simple (fd
, SMART_CMD_AUTO_OFFLINE
, 0xF8, TRUE
);
249 retval
= smart_cmd_simple (fd
, SMART_CMD_IMMEDIATE_OFFLINE
, 0, TRUE
);
252 smart_read_values (fd
, &values
);
253 smart_read_thresholds (fd
, &thresholds
);
254 retval
= values_not_passed (&values
, &thresholds
);
257 smart_read_values (fd
, &values
);
258 smart_read_thresholds (fd
, &thresholds
);
259 retval
= nagios (&values
, &thresholds
);
262 smart_read_values (fd
, &values
);
263 smart_read_thresholds (fd
, &thresholds
);
264 print_values (&values
, &thresholds
);
274 get_offline_text (int status
)
277 for (i
= 0; offline_status_text
[i
].text
; i
++) {
278 if (offline_status_text
[i
].value
== status
) {
279 return offline_status_text
[i
].text
;
288 smart_read_values (int fd
, values_t
* values
)
294 args
[2] = SMART_READ_VALUES
;
296 if (ioctl (fd
, HDIO_DRIVE_CMD
, &args
)) {
298 printf (_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror (errno
));
301 memcpy (values
, args
+ 4, 512);
308 values_not_passed (values_t
* p
, thresholds_t
* t
)
310 value_t
* value
= p
->values
;
311 threshold_t
* threshold
= t
->thresholds
;
315 for (i
= 0; i
< NR_ATTRIBUTES
; i
++) {
316 if (value
->id
&& threshold
->id
&& value
->id
== threshold
->id
) {
317 if (value
->value
<= threshold
->threshold
) {
327 return (passed
? -failed
: 2);
333 nagios (values_t
* p
, thresholds_t
* t
)
335 value_t
* value
= p
->values
;
336 threshold_t
* threshold
= t
->thresholds
;
337 int status
= OPERATIONAL
;
344 for (i
= 0; i
< NR_ATTRIBUTES
; i
++) {
345 if (value
->id
&& threshold
->id
&& value
->id
== threshold
->id
) {
346 if (value
->value
<= threshold
->threshold
) {
348 if (value
->status
& 1) {
367 printf (_("CRITICAL - %d Harddrive PreFailure%cDetected! %d/%d tests failed.\n"),
369 prefailure
> 1 ? 's' : ' ',
372 status
=STATE_CRITICAL
;
375 printf (_("WARNING - %d Harddrive Advisor%s Detected. %d/%d tests failed.\n"),
377 advisory
> 1 ? "ies" : "y",
380 status
=STATE_WARNING
;
383 printf (_("OK - Operational (%d/%d tests passed)\n"), passed
, total
);
387 printf (_("ERROR - Status '%d' unkown. %d/%d tests passed\n"), status
,
389 status
= STATE_UNKNOWN
;
398 print_value (value_t
* p
, threshold_t
* t
)
400 printf ("Id=%3d, Status=%2d {%s , %s}, Value=%3d, Threshold=%3d, %s\n",
401 p
->id
, p
->status
, p
->status
& 1 ? "PreFailure" : "Advisory ",
402 p
->status
& 2 ? "OnLine " : "OffLine", p
->value
, t
->threshold
,
403 p
->value
> t
->threshold
? "Passed" : "Failed");
409 print_values (values_t
* p
, thresholds_t
* t
)
411 value_t
* value
= p
->values
;
412 threshold_t
* threshold
= t
->thresholds
;
414 for (i
= 0; i
< NR_ATTRIBUTES
; i
++) {
415 if (value
->id
&& threshold
->id
&& value
->id
== threshold
->id
) {
416 print_value (value
++, threshold
++);
420 (_("OffLineStatus=%d {%s}, AutoOffLine=%s, OffLineTimeout=%d minutes\n"),
422 get_offline_text (p
->offline_status
& 0x7f),
423 (p
->offline_status
& 0x80 ? "Yes" : "No"),
424 p
->offline_timeout
/ 60);
426 (_("OffLineCapability=%d {%s %s %s}\n"),
427 p
->offline_capability
,
428 p
->offline_capability
& 1 ? "Immediate" : "",
429 p
->offline_capability
& 2 ? "Auto" : "",
430 p
->offline_capability
& 4 ? "AbortOnCmd" : "SuspendOnCmd");
432 (_("SmartRevision=%d, CheckSum=%d, SmartCapability=%d {%s %s}\n"),
436 p
->smart_capability
& 1 ? "SaveOnStandBy" : "",
437 p
->smart_capability
& 2 ? "AutoSave" : "");
442 smart_cmd_simple (int fd
, enum SmartCommand command
, __u8 val0
, char show_error
)
448 args
[2] = smart_command
[command
].value
;
450 if (ioctl (fd
, HDIO_DRIVE_CMD
, &args
)) {
453 printf (_("CRITICAL - %s: %s\n"), smart_command
[command
].text
, strerror (errno
));
462 smart_read_thresholds (int fd
, thresholds_t
* thresholds
)
468 args
[2] = SMART_READ_THRESHOLDS
;
470 if (ioctl (fd
, HDIO_DRIVE_CMD
, &args
)) {
472 printf (_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror (errno
));
475 memcpy (thresholds
, args
+ 4, 512);
483 print_revision (progname
, revision
);
485 printf ("Nagios feature - 1999 Robert Dale <rdale@digital-mission.com>\n");
486 printf ("(C) 1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>\n");
487 printf (COPYRIGHT
, copyright
, email
);
489 printf (_("This plugin checks a local hard drive with the (Linux specific) SMART interface [http://smartlinux.sourceforge.net/smart/index.php]."));
495 printf (_(UT_HELP_VRSN
));
496 printf (_(UT_EXTRA_OPTS
));
498 printf (" %s\n", "-d, --device=DEVICE");
499 printf (" %s\n", _("Select device DEVICE"));
500 printf (" %s\n", _("Note: if the device is selected with this option, _no_ other options are accepted"));
501 printf (" %s\n", "-i, --immediate");
502 printf (" %s\n", _("Perform immediately offline tests"));
503 printf (" %s\n", "-q, --quiet-check");
504 printf (" %s\n", _("Returns the number of failed tests"));
505 printf (" %s\n", "-1, --auto-on");
506 printf (" %s\n", _("Turn on automatic offline tests"));
507 printf (" %s\n", "-0, --auto-off");
508 printf (" %s\n", _("Turn off automatic offline tests"));
509 printf (" %s\n", "-n, --nagios");
510 printf (" %s\n", _("Output suitable for Nagios"));
514 printf ("%s\n", _("Notes:"));
515 printf (_(UT_EXTRA_OPTS_NOTES
));
518 printf (_(UT_SUPPORT
));
521 /* todo : add to the long nanual as example
523 * Run with: check_ide-smart --nagios [-d] <DRIVE>
524 * Where DRIVE is an IDE drive, ie. /dev/hda, /dev/hdb, /dev/hdc
526 * - Returns 0 on no errors
527 * - Returns 1 on advisories
528 * - Returns 2 on prefailure
529 * - Returns -1 not too often
536 printf (_("Usage:"));
537 printf ("%s [-d <device>] [-i <immediate>] [-q quiet] [-1 <auto-on>]",progname
);
538 printf (" [-O <auto-off>] [-n <nagios>]\n");