Subversion Repositories vnag

Rev

Rev 28 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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