Subversion Repositories vnag

Rev

Rev 28 | Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. <?php /* <ViaThinkSoftSignature>
  2. q7QvHyotKOTpEs9fbuwcPzqwjSw69WwJkY5ah30oJKbmru7P2dq3T8e5Xz2WZygTE
  3. JahCPsT59QVwK92IUQQDZwQ5QO1GBwhH9sQ2LoAy7W0X9iGLxwAQM1b0Lalfr22V0
  4. cct1CBNw2Jyv/jQXDdMGgJ0lEv677xH+zizO86+WahYUW6WZ91dFGp6gw89pMK4QA
  5. bvk6QnKmIrrfX/m6fA0SENoche/dBwFzSTSScpFCs6Xpy+aQNQUcGWyBKBePosQD0
  6. YI2TAqf7rnOuN71xgNG0JzNJQf+aBonZeBkxA98Iui4r10ws4iapq7TklJaWoy423
  7. iHUWx9PU+u5RqnthE98Dmcu/pJmQME8l/M4eSNFssUmc3Oxx3lcSMjyBmlTyOx9eA
  8. 24Fg5xaLH29nGP6XfuFdGrUUzkNZKWqG9jUQ1DBhSs/U3bFIABCIBnSB0kWlT18tP
  9. c9WLveDfdZG56c8Sw9lKKQZh1Nx1fhPa3Kq/a/JqJnWv3161M4LKSsw9038Qdzqad
  10. mYA0paiMPS5RLsJmktVn1NmTNudaW1QyLkwqKZAHuSof1M7/KOElZLu20ut4U/BRc
  11. xWvtQOtgdwE5s79WIzCT72Ycv1OHuwfdrdABwBx+t3gM0nx+EjZhyhcYm/O4j1FMs
  12. fvVnCkrl6wl1gJSJ5ADLvdaQFA9aGiH7UhBSEL77u6/962qshTaJ//OZhaWdoIIfn
  13. Dx9iwMjTm/x6qeLgwcYUonp59/76ZPQlFYzjf+M/pcqZ8XManfd9fADrau5+15k2h
  14. i18FVBi43Ef5rletQM2c39ZOBOlklILKxsQTNUWDjZCsSV7dVxJJq2ykcNruogppM
  15. hpXPgLBye0dWqxeAixQEoLegUgwxI/X3MP5qJbfxzQfBZYo54yEMaml+T4cGU6Ctj
  16. gkhxB05CMxaORs5f1dFmKBKKNvZ7pQw4g/GbRxhVX+uAdVf5e4oVFEYBNviCc4tGt
  17. MEHiPhTEa5PJbfRgxiEfyKkSjDXJeHou5O8mQjD/01cw3VMhuaStcM99DaAVunBWi
  18. 24uD1lLhHXybvwIiJ3OwA/oOmwL47UZ1fsKFHwMfEb4bQ9SiwosESz2V6TZHlQjbi
  19. 1tIfhmrsxG88jtYpBPagTD09afluSRJAmEiMzl4k2+JAts3mvfGFTl5KsGGard3gq
  20. zR5XlY52le3Oi0MFNQzXi+jeOJdWlIGbTb7z10rwrLemyGzFH4BPhwjV7gOlxpmE5
  21. xFb/VeAeGCPIh5XxNq34S82EV80MMw2DK1l7T3440cTteSv4byAE2ZWo3/iH1lOXp
  22. oUEulv7DBhHv1OZHbZsU9klfScZcQVJM+FmVqtK6krBZtx5p2a49N9kD0ZOn2lc6O
  23. w==
  24. </ViaThinkSoftSignature> */ ?>
  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.  *
  32.  * Revision 2022-05-11
  33.  */
  34.  
  35. declare(ticks=1);
  36.  
  37. class SmartCheck extends VNag {
  38.         protected $argType = null;
  39.  
  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.');
  54.                 $this->getHelpManager()->setSyntax('$SCRIPTNAME$ [-T <type>]');
  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.'));
  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.  
  77.                 $code = 0;
  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 {
  83.                         exec('sudo smartctl --all '.escapeshellarg($dev), $out, $code);
  84.                 }
  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.  
  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.  
  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. }
  186.