Subversion Repositories vnag

Rev

Rev 49 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4 daniel-mar 1
<?php /* <ViaThinkSoftSignature>
50 daniel-mar 2
MxM5IDmxLm4AvC7HzDxuwcSLYq57hKAe+rOy3+J8f3xVocgSffeNKPryAUV1XIDUQ
3
GsPaei87WN2j37pzhpMbxs73vTDip4vC5jQzYFurtVyC4JDZ3E4HKI2/X9w94FlI9
4
hjEvJ7hJ40i0YFRYhSIfDNqAnpvuWvcSZ4jADiakjVf3YQqfbcjazFX5gyRXH4F73
5
Ig+PHVFmhv5lc77x8sZqPggLIdxCCXWtuwPhwr95DTIYMLieIGlKO1uoytcDq9geI
6
EM7DWp7JPqECj8Z42jR+5Q4tt+EikyJ1/XX5eHDDI9e3p0bboq3l1SIXr9WQG5xtv
7
60EN4EGqCfJdLqDI29ETmH28JTOFReWkEr/Dcb9C569yeOWUi4L9h12BdKT5gxjOL
8
GXCHUfmrwss6Fl0s6EYmN03YEkCDsvHRna15Kf59J1r9h1yGrmpeBNLlS5+aHR81/
9
KYqeDF+ZMLmk2u1T4EpMVJ+QvLaGc4/a79vniZWZK/HRhIbV74WVu5yqGEzJ0dwij
10
QYDjUwRcz8GdfzBkEpUpIasRqWdKSgTAxKgW5GLFEXqJ4g9xsMmr2CD5dpDOBhwLQ
11
pHdI6WDGLp1NSts6hWyi7Yv8D+PYC07HMB4Lsk5b03eJ4BdGpyPTFpMKtMgBpCb9Q
12
oLU/E+j7Gv4CTJ8HEkg/oX8FGWs/EI1NpPwFa5m1Jb/CDvWc5d/tDUmxed14yxUAe
13
vbJbSkUYiULq7bl6nBwGLsaUbL+yrKHxh1ojl2e+/l8YlZAIkW702IZ9lukQ0HNzf
14
MHzho6z0UnAior+Y/C8wrGohDvbstBYErkq2MZLLotWy4y265AOi1UvnJXUBefDJH
15
j7M9UIkM8kycyplqyWCAWAfjF+yrMXWz+PH6lJm1N5ya0KoEfpLlRTlUcWkZEqOb4
16
B6z3AEoNzSmnvF62D0SQcvfY5idHhlOeyAVCCxr6ElHPTrh2TaQHg729OlaIRulvJ
17
+KX4hqIbJYHgXtLdQk4bLm+FE3GmgqGb7nAy0QQ/fv6ouHv3Dx3JZvYW1NSSCDSju
18
R6yJukTvuiWbwI4VgEDNk3sgqDHJHMg368OiRGSaHhdsssu5TIqA4jR/CxGj8VxOZ
19
9dtuoRlXQF16nSdzvx8YcI08c7jiYTffLo0AdYA8SGAqgc3qV2YKT1R61XiaG4N95
20
LaM8m4dquy1rJVRb+st4oph51o1cWHm5agHtEKitGOhxVbXE/AWHMiha3BMB9VJUi
21
FJKLq8yEQpoUEB45knhFn3/3XZUeWCj5TFy+IawBLfgLWpv9JvTCvHqFQ3DFW8jpS
22
OWgW4c7SOTM6yH5uExIRCqp/vbVaNcu0HU/RVU50UrdkkwQu6h+40+7EKFQHie/bZ
23
Q==
4 daniel-mar 24
</ViaThinkSoftSignature> */ ?>
2 daniel-mar 25
<?php
26
 
27
/*
28
 * VNag - Nagios Framework for PHP
29
 * Developed by Daniel Marschall, ViaThinkSoft <www.viathinksoft.com>
30
 * Licensed under the terms of the Apache 2.0 license
31
 *
49 daniel-mar 32
 * Revision 2022-05-11
2 daniel-mar 33
 */
34
 
35
declare(ticks=1);
36
 
37
class SmartCheck extends VNag {
49 daniel-mar 38
        protected $argType = null;
39
 
2 daniel-mar 40
        public function __construct() {
41
                parent::__construct();
42
 
43
                if ($this->is_http_mode()) {
44
                        // Don't allow the standard arguments via $_REQUEST
45
                        $this->registerExpectedStandardArguments('');
46
                } else {
47
                        $this->registerExpectedStandardArguments('Vhtv');
48
                }
49
 
50
                $this->getHelpManager()->setPluginName('vnag_smart');
51
                $this->getHelpManager()->setVersion('1.0');
52
                $this->getHelpManager()->setShortDescription('This plugin checks the contents of the SMART data and warns when a harddisk has failed.');
53
                $this->getHelpManager()->setCopyright('Copyright (C) 2011-$CURYEAR$ Daniel Marschall, ViaThinkSoft.');
49 daniel-mar 54
                $this->getHelpManager()->setSyntax('$SCRIPTNAME$ [-T <type>]');
2 daniel-mar 55
                $this->getHelpManager()->setFootNotes('If you encounter bugs, please contact ViaThinkSoft at www.viathinksoft.com');
49 daniel-mar 56
 
57
                // TODO: also add a command to check a single drive   [ -d /dev/sda,/dev/sdb ]
58
                // Individual (non-standard) arguments:
50 daniel-mar 59
                $this->addExpectedArgument($this->argType = new VNagArgument('T', 'type', VNagArgument::VALUE_REQUIRED, 'type', 'Explicit drive type e.g. for RAID devices "sat+cciss,0" for drive 0.'));
2 daniel-mar 60
        }
61
 
62
        private function check_smart($dev) {
63
                if (!`which which`) {
64
                        throw new VNagException("Program 'which' is not installed on your system");
65
                }
66
 
67
                if (!`which smartctl`) {
68
                        throw new VNagException("Program 'smartctl' (usually included in package smartmontools) is not installed on your system");
69
                }
70
 
71
                if (!`sudo cat /proc/cpuinfo`) {
72
                        // To make this work, please run "visudo" and add the following line:
73
                        // nagios ALL=NOPASSWD: /usr/sbin/smartctl
74
                        throw new VNagException("You don't have SUDO privileges. Please run 'visudo' and allow the command /usr/sbin/smartctl for user ".get_current_user().".");
75
                }
76
 
28 daniel-mar 77
                $code = 0;
78
                $out = array();
49 daniel-mar 79
 
80
                if ($this->argType->getValue() != '') {
81
                        exec('sudo smartctl --all '.escapeshellarg($dev).' -d '.escapeshellarg($this->argType->getValue()), $out, $code);
82
                } else {
83
                        exec('sudo smartctl --all '.escapeshellarg($dev), $out, $code);
84
                }
2 daniel-mar 85
                $cont = implode("\n", $out);
86
 
87
                $msg = array();
88
                $status = -1;
89
 
90
                if (stripos($cont, 'device lacks SMART capability') !== false)  {
91
                        // At my system (Debian 9), I get exit code 4 (which is not fully accurate)
92
                        $msg[] = 'Device lacks SMART capability';
93
                        #$status = VNag::STATUS_UNKNOWN;
94
                } else if ($code == 0) {
95
                        $status = VNag::STATUS_OK;
96
                } else {
97
                        if ($code & 1) {
98
                                throw new Exception("smartctl reports 'command line did not parse' (code $code).");
99
                        }
100
                        if ($code & 2) {
101
                                $msg[] = "Device open failed. It is either completely defective, or in low-power mode.";
102
                                $status = max($status, VNag::STATUS_CRITICAL);
103
                        }
104
                        if ($code & 4) {
105
                                $msg[] = "SMART command failed or checksum is wrong.";
106
                                $status = max($status, VNag::STATUS_WARNING);
107
                        }
108
                        if ($code & 8) {
109
                                $msg[] = "SMART status returns 'DISK FAILING'";
110
                                $status = max($status, VNag::STATUS_CRITICAL);
111
                        }
112
                        if ($code & 16) {
113
                                $msg[] = "SMART found prefail attributes below threshold";
114
                                $status = max($status, VNag::STATUS_WARNING);
115
                        }
116
                        if ($code & 32) {
117
                                $msg[] = "SMART status is 'OK' but usage/prefail attributes have been below threshold in the past.";
118
                                $status = max($status, VNag::STATUS_WARNING);
119
                        }
120
                        if ($code & 64) {
121
                                $msg[] = "The device error log contains records of errors.";
122
                                $status = max($status, VNag::STATUS_WARNING);
123
                        }
124
                        if ($code & 128) {
125
                                $msg[] = "The self-test logs contains records of errors.";
126
                                $status = max($status, VNag::STATUS_WARNING);
127
                        }
128
                }
129
 
130
                $messages = implode(", ", $msg);
131
                if ($messages != '') $messages = ": $messages";
132
 
133
                if ($status == VNag::STATUS_CRITICAL) {
134
                        $this->addVerboseMessage("$dev (Critical)$messages", VNag::VERBOSITY_SUMMARY);
135
                } else if ($status == VNag::STATUS_WARNING) {
136
                        $this->addVerboseMessage("$dev (Warning)$messages", VNag::VERBOSITY_SUMMARY);
137
                } else if ($status == VNag::STATUS_OK) {
138
                        $this->addVerboseMessage("$dev (OK)$messages", VNag::VERBOSITY_ADDITIONAL_INFORMATION);
139
                } else {
140
                        $status = VNag::STATUS_UNKNOWN;
141
                        $this->addVerboseMessage("$dev (Unknown)$messages", VNag::VERBOSITY_SUMMARY);
142
                }
143
                $this->setStatus($status);
144
                return $status;
145
        }
146
 
147
        protected function cbRun() {
148
                $devices = array();
149
                $devices = array_merge($devices, glob('/dev/sd?'));
150
                $devices = array_merge($devices, glob('/dev/hd?'));
151
 
49 daniel-mar 152
                if (count($devices) == 0) {
153
                        throw new Exception("No SDx or HDx drives found");
154
                }
155
 
156
                if (strpos($this->argType->getValue(),'cciss') !== false) {
157
                        $devices = array($devices[0]); // we just need a "fake" drive; the drive number is given as parameter to cciss
158
                }
159
 
2 daniel-mar 160
                $count_total = 0;
161
                $count_ok = 0;
162
                $count_warning = 0;
163
                $count_critical = 0;
164
                $count_unknown = 0;
165
                foreach ($devices as $dev) {
166
                        $count_total++;
167
                        switch ($this->check_smart($dev)) {
168
                                case VNag::STATUS_OK:
169
                                        $count_ok++;
170
                                        break;
171
                                case VNag::STATUS_WARNING:
172
                                        $count_warning++;
173
                                        break;
174
                                case VNag::STATUS_CRITICAL:
175
                                        $count_critical++;
176
                                        break;
177
                                case VNag::STATUS_UNKNOWN:
178
                                        $count_unknown++;
179
                                        break;
180
                        }
181
                }
182
 
183
                $this->setHeadline(sprintf('Checked %d drives (%d OK, %d warning, %d critical, %d unknown)', $count_total, $count_ok, $count_warning, $count_critical, $count_unknown));
184
        }
185
}