Subversion Repositories vnag

Rev

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

Rev 52 Rev 53
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 2022-05-11
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;
38
        protected $argType = null;
39
 
39
 
40
        public function __construct() {
40
        public function __construct() {
41
                parent::__construct();
41
                parent::__construct();
42
 
42
 
43
                if ($this->is_http_mode()) {
43
                if ($this->is_http_mode()) {
44
                        // Don't allow the standard arguments via $_REQUEST
44
                        // Don't allow the standard arguments via $_REQUEST
45
                        $this->registerExpectedStandardArguments('');
45
                        $this->registerExpectedStandardArguments('');
46
                } else {
46
                } else {
47
                        $this->registerExpectedStandardArguments('Vhtv');
47
                        $this->registerExpectedStandardArguments('Vhtv');
48
                }
48
                }
49
 
49
 
50
                $this->getHelpManager()->setPluginName('vnag_smart');
50
                $this->getHelpManager()->setPluginName('vnag_smart');
51
                $this->getHelpManager()->setVersion('1.0');
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.');
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.');
53
                $this->getHelpManager()->setCopyright('Copyright (C) 2011-$CURYEAR$ Daniel Marschall, ViaThinkSoft.');
54
                $this->getHelpManager()->setSyntax('$SCRIPTNAME$ [-T <type>]');
54
                $this->getHelpManager()->setSyntax('$SCRIPTNAME$ [-T <type>]');
55
                $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
 
56
 
57
                // TODO: also add a command to check a single drive   [ -d /dev/sda,/dev/sdb ]
57
                // TODO: also add a command to check a single drive   [ -d /dev/sda,/dev/sdb ]
58
                // Individual (non-standard) arguments:
58
                // Individual (non-standard) arguments:
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.'));
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.'));
60
        }
60
        }
61
 
61
 
62
        private function check_smart($dev) {
62
        private function check_smart($dev) {
63
                if (!`which which`) {
63
                if (!`which which`) {
64
                        throw new VNagException("Program 'which' is not installed on your system");
64
                        throw new VNagException("Program 'which' is not installed on your system");
65
                }
65
                }
66
 
66
 
67
                if (!`which smartctl`) {
67
                if (!`which smartctl`) {
68
                        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");
69
                }
69
                }
70
 
70
 
71
                $code = 0;
71
                $code = 0;
72
                $out = array();
72
                $out = array();
73
 
73
 
74
                // TODO: For some reason, it does not work if "sudo" is added to the command section in icinga2.conf!
-
 
75
                if ($this->argType->getValue() != '') {
74
                if ($this->argType->getValue() != '') {
-
 
75
                        // Note: Requires root
76
                        exec('sudo smartctl --all '.escapeshellarg($dev).' -d '.escapeshellarg($this->argType->getValue()), $out, $code);
76
                        exec('smartctl --all '.escapeshellarg($dev).' -d '.escapeshellarg($this->argType->getValue()), $out, $code);
77
                } else {
77
                } else {
-
 
78
                        // Note: Requires root
78
                        exec('sudo smartctl --all '.escapeshellarg($dev), $out, $code);
79
                        exec('smartctl --all '.escapeshellarg($dev), $out, $code);
79
                }
80
                }
80
                $cont = implode("\n", $out);
81
                $cont = implode("\n", $out);
81
 
82
 
82
                $msg = array();
83
                $msg = array();
83
                $status = -1;
84
                $status = -1;
84
 
85
 
85
                if (stripos($cont, 'device lacks SMART capability') !== false)  {
86
                if (stripos($cont, 'device lacks SMART capability') !== false)  {
86
                        // At my system (Debian 9), I get exit code 4 (which is not fully accurate)
87
                        // At my system (Debian 9), I get exit code 4 (which is not fully accurate)
87
                        $msg[] = 'Device lacks SMART capability';
88
                        $msg[] = 'Device lacks SMART capability';
88
                        #$status = VNag::STATUS_UNKNOWN;
89
                        #$status = VNag::STATUS_UNKNOWN;
89
                } else if ($code == 0) {
90
                } else if ($code == 0) {
90
                        $status = VNag::STATUS_OK;
91
                        $status = VNag::STATUS_OK;
91
                } else {
92
                } else {
92
                        if ($code & 1) {
93
                        if ($code & 1) {
93
                                throw new Exception("smartctl reports 'command line did not parse' (code $code).");
94
                                throw new Exception("smartctl reports 'command line did not parse' (code $code).");
94
                        }
95
                        }
95
                        if ($code & 2) {
96
                        if ($code & 2) {
96
                                $msg[] = "Device open failed. It is either completely defective, or in low-power mode.";
97
                                $msg[] = "Device open failed. It is either completely defective, or in low-power mode.";
97
                                $status = max($status, VNag::STATUS_CRITICAL);
98
                                $status = max($status, VNag::STATUS_CRITICAL);
98
                        }
99
                        }
99
                        if ($code & 4) {
100
                        if ($code & 4) {
100
                                $msg[] = "SMART command failed or checksum is wrong.";
101
                                $msg[] = "SMART command failed or checksum is wrong.";
101
                                $status = max($status, VNag::STATUS_WARNING);
102
                                $status = max($status, VNag::STATUS_WARNING);
102
                        }
103
                        }
103
                        if ($code & 8) {
104
                        if ($code & 8) {
104
                                $msg[] = "SMART status returns 'DISK FAILING'";
105
                                $msg[] = "SMART status returns 'DISK FAILING'";
105
                                $status = max($status, VNag::STATUS_CRITICAL);
106
                                $status = max($status, VNag::STATUS_CRITICAL);
106
                        }
107
                        }
107
                        if ($code & 16) {
108
                        if ($code & 16) {
108
                                $msg[] = "SMART found prefail attributes below threshold";
109
                                $msg[] = "SMART found prefail attributes below threshold";
109
                                $status = max($status, VNag::STATUS_WARNING);
110
                                $status = max($status, VNag::STATUS_WARNING);
110
                        }
111
                        }
111
                        if ($code & 32) {
112
                        if ($code & 32) {
112
                                $msg[] = "SMART status is 'OK' but usage/prefail attributes have been below threshold in the past.";
113
                                $msg[] = "SMART status is 'OK' but usage/prefail attributes have been below threshold in the past.";
113
                                $status = max($status, VNag::STATUS_WARNING);
114
                                $status = max($status, VNag::STATUS_WARNING);
114
                        }
115
                        }
115
                        if ($code & 64) {
116
                        if ($code & 64) {
116
                                $msg[] = "The device error log contains records of errors.";
117
                                $msg[] = "The device error log contains records of errors.";
117
                                $status = max($status, VNag::STATUS_WARNING);
118
                                $status = max($status, VNag::STATUS_WARNING);
118
                        }
119
                        }
119
                        if ($code & 128) {
120
                        if ($code & 128) {
120
                                $msg[] = "The self-test logs contains records of errors.";
121
                                $msg[] = "The self-test logs contains records of errors.";
121
                                $status = max($status, VNag::STATUS_WARNING);
122
                                $status = max($status, VNag::STATUS_WARNING);
122
                        }
123
                        }
123
                }
124
                }
124
 
125
 
125
                $messages = implode(", ", $msg);
126
                $messages = implode(", ", $msg);
126
                if ($messages != '') $messages = ": $messages";
127
                if ($messages != '') $messages = ": $messages";
127
 
128
 
128
                if ($status == VNag::STATUS_CRITICAL) {
129
                if ($status == VNag::STATUS_CRITICAL) {
129
                        $this->addVerboseMessage("$dev (Critical)$messages", VNag::VERBOSITY_SUMMARY);
130
                        $this->addVerboseMessage("$dev (Critical)$messages", VNag::VERBOSITY_SUMMARY);
130
                } else if ($status == VNag::STATUS_WARNING) {
131
                } else if ($status == VNag::STATUS_WARNING) {
131
                        $this->addVerboseMessage("$dev (Warning)$messages", VNag::VERBOSITY_SUMMARY);
132
                        $this->addVerboseMessage("$dev (Warning)$messages", VNag::VERBOSITY_SUMMARY);
132
                } else if ($status == VNag::STATUS_OK) {
133
                } else if ($status == VNag::STATUS_OK) {
133
                        $this->addVerboseMessage("$dev (OK)$messages", VNag::VERBOSITY_ADDITIONAL_INFORMATION);
134
                        $this->addVerboseMessage("$dev (OK)$messages", VNag::VERBOSITY_ADDITIONAL_INFORMATION);
134
                } else {
135
                } else {
135
                        $status = VNag::STATUS_UNKNOWN;
136
                        $status = VNag::STATUS_UNKNOWN;
136
                        $this->addVerboseMessage("$dev (Unknown)$messages", VNag::VERBOSITY_SUMMARY);
137
                        $this->addVerboseMessage("$dev (Unknown)$messages", VNag::VERBOSITY_SUMMARY);
137
                }
138
                }
138
                $this->setStatus($status);
139
                $this->setStatus($status);
139
                return $status;
140
                return $status;
140
        }
141
        }
141
 
142
 
142
        protected function cbRun() {
143
        protected function cbRun() {
143
                $devices = array();
144
                $devices = array();
144
                $devices = array_merge($devices, glob('/dev/sd?'));
145
                $devices = array_merge($devices, glob('/dev/sd?'));
145
                $devices = array_merge($devices, glob('/dev/hd?'));
146
                $devices = array_merge($devices, glob('/dev/hd?'));
146
 
147
 
147
                if (count($devices) == 0) {
148
                if (count($devices) == 0) {
148
                        throw new Exception("No SDx or HDx drives found");
149
                        throw new Exception("No SDx or HDx drives found");
149
                }
150
                }
150
 
151
 
151
                if (strpos($this->argType->getValue(),'cciss') !== false) {
152
                if (strpos($this->argType->getValue(),'cciss') !== false) {
152
                        $devices = array($devices[0]); // we just need a "fake" drive; the drive number is given as parameter to cciss
153
                        $devices = array($devices[0]); // we just need a "fake" drive; the drive number is given as parameter to cciss
153
                }
154
                }
154
 
155
 
155
                $count_total = 0;
156
                $count_total = 0;
156
                $count_ok = 0;
157
                $count_ok = 0;
157
                $count_warning = 0;
158
                $count_warning = 0;
158
                $count_critical = 0;
159
                $count_critical = 0;
159
                $count_unknown = 0;
160
                $count_unknown = 0;
160
                foreach ($devices as $dev) {
161
                foreach ($devices as $dev) {
161
                        $count_total++;
162
                        $count_total++;
162
                        switch ($this->check_smart($dev)) {
163
                        switch ($this->check_smart($dev)) {
163
                                case VNag::STATUS_OK:
164
                                case VNag::STATUS_OK:
164
                                        $count_ok++;
165
                                        $count_ok++;
165
                                        break;
166
                                        break;
166
                                case VNag::STATUS_WARNING:
167
                                case VNag::STATUS_WARNING:
167
                                        $count_warning++;
168
                                        $count_warning++;
168
                                        break;
169
                                        break;
169
                                case VNag::STATUS_CRITICAL:
170
                                case VNag::STATUS_CRITICAL:
170
                                        $count_critical++;
171
                                        $count_critical++;
171
                                        break;
172
                                        break;
172
                                case VNag::STATUS_UNKNOWN:
173
                                case VNag::STATUS_UNKNOWN:
173
                                        $count_unknown++;
174
                                        $count_unknown++;
174
                                        break;
175
                                        break;
175
                        }
176
                        }
176
                }
177
                }
177
 
178
 
178
                $this->setHeadline(sprintf('Checked %d drives (%d OK, %d warning, %d critical, %d unknown)', $count_total, $count_ok, $count_warning, $count_critical, $count_unknown));
179
                $this->setHeadline(sprintf('Checked %d drives (%d OK, %d warning, %d critical, %d unknown)', $count_total, $count_ok, $count_warning, $count_critical, $count_unknown));
179
        }
180
        }
180
}
181
}
181
 
182