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 | } |