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 |