├── .gitmodules ├── README.md ├── check_arista_chassis_api.php ├── check_barracuda_lb_active.pl ├── check_bgpstatus.pl ├── check_chassis_brocade.php ├── check_chassis_brocade.pl ├── check_chassis_cisco.pl ├── check_chassis_extreme.php ├── check_chassis_juniper_mx204.php ├── check_chassis_mikrotik.php ├── check_chassis_server.pl ├── check_disk_snmp.pl ├── check_pop3_login.pl ├── check_port_errors.php ├── check_portsecurity.pl ├── check_portstatus.pl ├── check_processes_snmp.pl ├── check_radius.sh ├── check_rsnapshot.php └── notify-by-pushover.php /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "OSS_SNMP"] 2 | path = OSS_SNMP 3 | url = https://github.com/opensolutions/OSS_SNMP.git 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Nagios Plugins :: nagios-plugins 2 | ================================ 3 | 4 | Introduction 5 | ------------ 6 | 7 | `nagios-plugins` is a collection of various plugins written and expanded 8 | over since circa 2005. They main goal of Nagios plugins available and released 9 | here are: 10 | 11 | * BSD (or BSD like) license so you can hack away to wield into something that 12 | may be more suitable for your own environment; 13 | * scalable in that if I am polling power supply units (PSUs) in a Cisco switch 14 | then it should not matter if there is one or a hundred - the script should 15 | handle them all; 16 | * WARNINGs are designed for email notifications during working hours; CRITICAL 17 | means an out of hours text / SMS message :( 18 | * Perl is not my first language but many scripts are written in Perl. 19 | * each script should be an independant unit with no dependancies on each 20 | other or unusual Perl modules; 21 | * the scripts should all be run with the `--verbose` on new kit. This will 22 | provide an inventory of what it finds as well as show anything that is being 23 | skipped. OIDs searched for by the script but reported as not supported on 24 | the target device should really be skipped via various `--skip-xxx` options. 25 | * useful help available via `--help` or `-?` or `--man`` 26 | 27 | Installation 28 | ------------ 29 | 30 | ```sh 31 | git clone https://github.com/barryo/nagios-plugins.git 32 | cd nagios-plugins/ 33 | git submodule init 34 | git submodule update 35 | ``` 36 | 37 | SNMPv3 support 38 | -------------- 39 | 40 | SNMPv3 support requires additional packages for the perl plugins. On a 41 | Debian / Ubuntu system, these can be installed using the following command 42 | line: 43 | 44 | ``` 45 | apt install libnet-snmp-perl libnet-ip-perl libcrypt-des-perl libdigest-hmac-perl libcrypt-rijndael-perl 46 | ``` 47 | 48 | License 49 | ------- 50 | 51 | Unless stated otherwise at the top of the script of its help output, all scripts 52 | are: 53 | 54 | Copyright (c) 2004 - 2014, Barry O'Donovan 55 | Copyright (c) 2004 - 2014, Open Source Solutions Limited 56 | All rights reserved. 57 | 58 | Redistribution and use in source and binary forms, with or without modification, 59 | are permitted provided that the following conditions are met: 60 | 61 | * Redistributions of source code must retain the above copyright notice, this 62 | list of conditions and the following disclaimer. 63 | 64 | * Redistributions in binary form must reproduce the above copyright notice, this 65 | list of conditions and the following disclaimer in the documentation and/or 66 | other materials provided with the distribution. 67 | 68 | * Neither the name of Open Solutions nor the names of its contributors may be 69 | used to endorse or promote products derived from this software without 70 | specific prior written permission. 71 | 72 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 73 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 74 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 75 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 76 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 77 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 78 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 79 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 80 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 81 | OF THE POSSIBILITY OF SUCH DAMAGE. 82 | 83 | About the Author 84 | ---------------- 85 | 86 | The primary author is Barry O'Donovan with contributions by others (see Git history). 87 | 88 | Please see my company website at https://www.islandbridgenetworks.ie/ or my own personal 89 | site at http://www.barryodonovan.com/. 90 | 91 | 92 | 93 | Overview of Available Plugins 94 | ----------------------------- 95 | 96 | ### check_rsnapshot.php 97 | 98 | A script to check backups made via rsnapshot. See https://github.com/barryo/nagios-plugins/wiki/check_rsnapshot.php. 99 | 100 | ### check_barracuda_lb_active.pl 101 | 102 | A script to check if a given Barracuda load balance in high availability state 103 | is in active (or inactive) mode for a given IP address. 104 | 105 | ### check_chassis_cisco.pl 106 | 107 | This script polls a Cisco switch or router and checks and generates alerts on the following items: 108 | 109 | * a warning if the device was recently rebooted; 110 | * a warning / critical if any found temperature sensors are in a non-normal state; 111 | * a warning / critical if any found fans are in a non-normal state; 112 | * a warning / critical if any found PSUs are in a non-normal state; 113 | * a warning / critical if the 5 sec / 1 min / 5 min CPU utilisation is above set thresholds; 114 | * a warning / critical if the memory utilisation is above set thresholds. 115 | 116 | ### check_chassis_brocade.pl / .php 117 | 118 | **NB:** the .php version is more modern. 119 | 120 | This script polls a Brocade switch or router and checks and generates alerts on the following items: 121 | 122 | * a warning if the device was recently rebooted; 123 | * a warning / critical if any found temperature sensors are in a non-normal state; 124 | * a warning / critical if any found fans are in a non-normal state; 125 | * a warning / critical if any found PSUs are in a non-normal state; 126 | * a warning / critical if the 5 sec / 1 min / 5 min CPU utilisation is above set thresholds; 127 | * a warning / critical if the memory utilisation is above set thresholds. 128 | 129 | ### check_chassis_extreme.php 130 | 131 | This script polls an Extreme Networks switch or router and checks and generates alerts on the following items: 132 | 133 | * a warning if the device was recently rebooted; 134 | * a warning / critical if any found temperature sensors are in a non-normal state; 135 | * a warning / critical if any found fans are in a non-normal state; 136 | * a warning / critical if any found PSUs are in a non-normal state; 137 | * a warning / critical if the 5 sec CPU utilisation is above set thresholds; 138 | * a warning / critical if the memory utilisation is above set thresholds. 139 | 140 | ### check_chassis_server.pl 141 | 142 | This script polls a Linux / BSD server and checks and generates alerts on the following items: 143 | 144 | * a warning if the device was recently rebooted; 145 | * a warning / critical if the 1/5/15 min load average is above thresholds set in the servers SNMP config file; 146 | * a warning / critical if the memory or swap utilisation is above set thresholds. 147 | 148 | Note that you may want to set swap warning threshold low (default is 20%) as you will want to know 149 | if you're using swap. If anyone is very familiar with the BSD memory model, I'd appreciate it if they 150 | could look that section over as it's more suited for Linux right now. 151 | 152 | ### check_disk_snmp.pl 153 | 154 | This script polls a Linux / BSD server and checks and generates alerts if disk utilisation 155 | approaches warning and critical thresholds. Example Nagios output: 156 | 157 | OK - /var (/dev/sda7) 70%; /home (/dev/sda10) 74%; /tmp (/dev/sda8) 3%; /usr (/dev/sda5) 76%; /usr/local (/dev/sda6) 4%; / (/dev/sda9) 30%; /boot (/dev/sda2) 64%; 158 | 159 | There is comprehensive help via the `--man` switch. 160 | 161 | 162 | ### check_portsecurity.pl 163 | 164 | This script checks all ports on a Cisco switch and issues a critical alert if port security has 165 | been triggered resulting in a shutdown port on the device. 166 | 167 | 168 | ### check_portstatus.pl 169 | 170 | This script will issue warnings if the port status on any Ethernet (by default) port on a Cisco 171 | switch has changed within the last hour (by default). I.e. a port up or a port down event. 172 | 173 | 174 | ### notify-by-pushover.php 175 | 176 | This script sends Nagios plugins to Pushover - see https://pushover.net/ and 177 | http://www.barryodonovan.com/index.php/2013/05/31/nagios-icinga-alerts-via-pushover 178 | 179 | 180 | -------------------------------------------------------------------------------- /check_arista_chassis_api.php: -------------------------------------------------------------------------------- 1 | #! /usr/bin/php 2 | 52 | * @author The Skilled Team of PHP Developers at Open Solutions 53 | */ 54 | 55 | date_default_timezone_set('Europe/Dublin'); 56 | define( "VERSION", '1.1.0' ); 57 | 58 | ini_set( 'max_execution_time', '55' ); 59 | 60 | ini_set( 'display_errors', true ); 61 | ini_set( 'display_startup_errors', true ); 62 | 63 | define( "STATUS_OK", 0 ); 64 | define( "STATUS_WARNING", 1 ); 65 | define( "STATUS_CRITICAL", 2 ); 66 | define( "STATUS_UNKNOWN", 3 ); 67 | 68 | define( "LOG__NONE", 0 ); 69 | define( "LOG__ERROR", 1 ); 70 | define( "LOG__VERBOSE", 2 ); 71 | define( "LOG__DEBUG", 3 ); 72 | 73 | // initialise some variables 74 | $status = STATUS_OK; 75 | $log_level = LOG__NONE; 76 | 77 | 78 | // possible output strings 79 | $criticals = ""; 80 | $warnings = ""; 81 | $unknowns = ""; 82 | $normals = ""; 83 | 84 | // set default values for command line arguments 85 | $cmdargs = [ 86 | 'username' => 'xxx', 87 | 'password' => 'xxx', 88 | 'log_level' => LOG__NONE, 89 | 'memwarn' => 85, 90 | 'memcrit' => 90, 91 | 'reboot' => 3600, 92 | 'thres-cpu-1sec' => '95,98', 93 | 'thres-cpu-5sec' => '85,95', 94 | 'thres-cpu-1min' => '70,90', 95 | 'target' => null, 96 | ]; 97 | 98 | 99 | // parse the command line arguments 100 | parseArguments(); 101 | 102 | 103 | //print_r( $cmdargs ); die(); 104 | 105 | 106 | if( $cmdargs['target'] === null || in_array( $cmdargs['target'], [ 'COOLING', 'POWER', 'TEMPERATURE', 'MEMORY' ] ) ) { 107 | 108 | $payload = '{ 109 | "jsonrpc": "2.0", 110 | "method": "runCmds", 111 | "params": { 112 | "format": "json", 113 | "timestamps": false, 114 | "autoComplete": false, 115 | "expandAliases": false, 116 | "cmds": [ 117 | "show system environment cooling", 118 | "show system environment power", 119 | "show system environment temperature", 120 | "show version" 121 | ], 122 | "version": 1 123 | }, 124 | "id": "EapiExplorer-1" 125 | }'; 126 | 127 | $ch = curl_init(); 128 | curl_setopt($ch, CURLOPT_URL, $cmdargs['api_url']); 129 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 130 | curl_setopt($ch, CURLOPT_USERPWD, "{$cmdargs['username']}:{$cmdargs['password']}"); 131 | curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); 132 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); 133 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 134 | curl_setopt($ch, CURLOPT_POST, 1); 135 | curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); 136 | curl_setopt($ch, CURLOPT_HTTPHEADER, array( 137 | 'Content-Type: application/json', 138 | 'Content-Length: ' . strlen($payload)) 139 | ); 140 | $output = curl_exec($ch); 141 | $info = curl_getinfo($ch); 142 | curl_close($ch); 143 | 144 | if( $info['http_code'] != 200 ) { 145 | echo "UNKNOWN: Could not access API interface"; 146 | exit( STATUS_UNKNOWN ); 147 | } 148 | 149 | if( !( $state = json_decode( $output ) ) ) { 150 | echo "UNKNOWN: Could not decode JSON response"; 151 | exit( STATUS_UNKNOWN ); 152 | } 153 | 154 | if( isset( $state->error ) ) { 155 | echo "UNKNOWN: " . $state->error->message; 156 | exit( STATUS_UNKNOWN ); 157 | } 158 | 159 | $state = $state->result; 160 | 161 | if( $cmdargs['target'] === null || $cmdargs['target'] === 'COOLING' ) { 162 | checkCooling( $state[0] ); 163 | } 164 | 165 | if( $cmdargs['target'] === null || $cmdargs['target'] === 'POWER' ) { 166 | checkPower( $state[1] ); 167 | } 168 | 169 | if( $cmdargs['target'] === null || $cmdargs['target'] === 'TEMPERATURE' ) { 170 | checkTemperature( $state[2] ); 171 | } 172 | 173 | if( $cmdargs['target'] === null || $cmdargs['target'] === 'MEMORY' ) { 174 | checkMemory( $state[3] ); 175 | } 176 | 177 | } 178 | 179 | if( $cmdargs['target'] === null || in_array( $cmdargs['target'], [ 'UPTIME', 'CPU' ] ) ) { 180 | 181 | $payload = '{ 182 | "jsonrpc": "2.0", 183 | "method": "runCmds", 184 | "params": { 185 | "format": "json", 186 | "timestamps": false, 187 | "autoComplete": false, 188 | "expandAliases": false, 189 | "cmds": [ 190 | "show uptime" 191 | ], 192 | "version": 1 193 | }, 194 | "id": "EapiExplorer-1" 195 | }'; 196 | 197 | $ch = curl_init(); 198 | curl_setopt($ch, CURLOPT_URL, $cmdargs['api_url']); 199 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 200 | curl_setopt($ch, CURLOPT_USERPWD, "{$cmdargs['username']}:{$cmdargs['password']}"); 201 | curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); 202 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); 203 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); 204 | curl_setopt($ch, CURLOPT_POST, 1); 205 | curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); 206 | curl_setopt($ch, CURLOPT_HTTPHEADER, array( 207 | 'Content-Type: application/json', 208 | 'Content-Length: ' . strlen($payload)) 209 | ); 210 | $output = curl_exec($ch); 211 | $info = curl_getinfo($ch); 212 | curl_close($ch); 213 | 214 | if( $info['http_code'] != 200 ) { 215 | echo "UNKNOWN: Could not access API interface for uptime"; 216 | exit( STATUS_UNKNOWN ); 217 | } 218 | 219 | if( !( $state = json_decode( $output ) ) ) { 220 | echo "UNKNOWN: Could not decode JSON response for uptime"; 221 | exit( STATUS_UNKNOWN ); 222 | } 223 | 224 | if( isset( $state->error ) ) { 225 | echo "UNKNOWN: (uptime) " . $state->error->message; 226 | exit( STATUS_UNKNOWN ); 227 | } 228 | 229 | $state = $state->result[0]; 230 | 231 | if( $cmdargs['target'] === null || $cmdargs['target'] === 'UPTIME' ) { 232 | checkUptime( round($state->upTime / 60) ); 233 | } 234 | 235 | if( $cmdargs['target'] === null || $cmdargs['target'] === 'CPU' ) { 236 | checkCPU( $state->loadAvg[0], $state->loadAvg[1], $state->loadAvg[2] ); 237 | } 238 | } 239 | 240 | 241 | if( $status == STATUS_OK ) 242 | $msg = "OK -{$normals}\n"; 243 | else 244 | $msg = "{$criticals}{$warnings}{$unknowns}\n"; 245 | 246 | echo $msg; 247 | exit( $status ); 248 | 249 | 250 | function checkCPU( $l1, $l2, $l3 ) { 251 | global $cmdargs, $criticals, $warnings, $unknowns, $normals; 252 | 253 | if( $l1 > 7 || $l2 > 5 || $l3 > 3 ) { 254 | setStatus( STATUS_WARNING ); 255 | $criticals .= "System load is high: {$l1} {$l2} {$l3}. "; 256 | } else { 257 | $normals .= "System load looks okay: {$l1} {$l2} {$l3}. "; 258 | } 259 | } 260 | 261 | function checkUptime( $num ) { 262 | global $cmdargs, $criticals, $warnings, $unknowns, $normals; 263 | 264 | if( isset( $cmdargs['skip-reboot'] ) && $cmdargs['skip-reboot'] ) 265 | return; 266 | 267 | if( $num < $cmdargs['reboot'] / 60 ) { 268 | setStatus( STATUS_CRITICAL ); 269 | $criticals .= "Switch uptime is {$num} minutes. "; 270 | } else { 271 | $normals .= " System uptime looks okay: {$num} minutes. "; 272 | } 273 | } 274 | 275 | function checkCooling( $fans ) { 276 | global $cmdargs, $criticals, $warnings, $unknowns, $normals; 277 | 278 | if( isset( $cmdargs['skip-fans'] ) && $cmdargs['skip-fans'] ) 279 | return; 280 | 281 | $fandata = 'Fans (speed actual/configured): '; 282 | 283 | foreach( $fans->fanTraySlots as $i => $ft ) { 284 | 285 | $fandata .= ( $i == 0 ? '' : '; ' ); 286 | 287 | $fandata .= "Tray {$ft->label}: "; 288 | 289 | foreach( $ft->fans as $f ) { 290 | $fandata .= "{$f->label} {$f->status} ({$f->actualSpeed}%/{$f->configuredSpeed}%)"; 291 | } 292 | 293 | if( $f->status != 'ok' ) { 294 | setStatus( STATUS_CRITICAL ); 295 | $criticals .= "Fan state for {$f->label}: {$f->status}"; 296 | } 297 | } 298 | 299 | foreach( $fans->powerSupplySlots as $i => $ft ) { 300 | 301 | $fandata .= ( $i == 0 ? '' : '; ' ); 302 | 303 | $fandata .= "Tray {$ft->label}: "; 304 | 305 | foreach( $ft->fans as $f ) { 306 | $fandata .= "{$f->label} {$f->status} ({$f->actualSpeed}%/{$f->configuredSpeed}%)"; 307 | } 308 | 309 | if( $f->status != 'ok' ) { 310 | setStatus( STATUS_CRITICAL ); 311 | $criticals .= "Fan state for {$f->label}: {$f->status}. "; 312 | } 313 | } 314 | 315 | $normals .= " $fandata. "; 316 | } 317 | 318 | function checkPower( $psus ) { 319 | global $cmdargs, $criticals, $warnings, $unknowns, $normals; 320 | 321 | if( isset( $cmdargs['skip-psu'] ) && $cmdargs['skip-psu'] ) 322 | return; 323 | 324 | $psudata = 'PSUs: '; 325 | $i = 1; 326 | 327 | while( isset( $psus->powerSupplies->$i ) ) { 328 | 329 | $psu = $psus->powerSupplies->$i; 330 | 331 | $psudata .= ( $i == 1 ? '' : '; ' ); 332 | 333 | $psudata .= "PSU #{$i} {$psu->modelName}: {$psu->state} ({$psu->outputPower}/{$psu->capacity}W)"; 334 | 335 | if( $psu->state != 'ok' ) { 336 | setStatus( STATUS_CRITICAL ); 337 | $criticals .= "PSU state for PSU #{$i} {$psu->modelName}: {$psu->state}. "; 338 | } 339 | 340 | $i++; 341 | } 342 | 343 | $normals .= " $psudata. "; 344 | } 345 | 346 | function checkTemperature( $temps ) { 347 | global $cmdargs, $criticals, $warnings, $unknowns, $normals; 348 | 349 | if( isset( $cmdargs['skip-temp'] ) && $cmdargs['skip-temp'] ) 350 | return; 351 | 352 | $data = 'Temperature (current/max/warn/crit): '; 353 | 354 | if( $temps->systemStatus == 'temperatureOk' ) { 355 | $data .= "overall system temperature status: ok. "; 356 | } else { 357 | setStatus( STATUS_CRITICAL ); 358 | $criticals .= "Overall system temperature status: {$temps->systemStatus}. "; 359 | } 360 | 361 | foreach( $temps->powerSupplySlots as $i => $t ) { 362 | 363 | foreach( $t->tempSensors as $ts ) { 364 | $data .= "{$ts->name} ({$ts->description}): {$ts->hwStatus} " 365 | . "({$ts->currentTemperature}/{$ts->maxTemperature}/{$ts->overheatThreshold}/{$ts->criticalThreshold}); "; 366 | 367 | if( $ts->inAlertState ) { 368 | setStatus( STATUS_CRITICAL ); 369 | $criticals .= "Temp sensor {$ts->name} ({$ts->description}) in alert state. "; 370 | } else if( $ts->currentTemperature >= $ts->criticalThreshold ) { 371 | setStatus( STATUS_CRITICAL ); 372 | $criticals .= "Temp sensor {$ts->name} ({$ts->description}) is >= critical threshold. "; 373 | } else if( $ts->currentTemperature >= $ts->overheatThreshold ) { 374 | setStatus( STATUS_WARNING ); 375 | $criticals .= "Temp sensor {$ts->name} ({$ts->description}) is >= overheat threshold. "; 376 | } 377 | } 378 | } 379 | 380 | foreach( $temps->tempSensors as $ts ) { 381 | $data .= "{$ts->name} ({$ts->description}): {$ts->hwStatus} " 382 | . "({$ts->currentTemperature}/{$ts->maxTemperature}/{$ts->overheatThreshold}/{$ts->criticalThreshold}); "; 383 | 384 | if( $ts->inAlertState ) { 385 | setStatus( STATUS_CRITICAL ); 386 | $criticals .= "Temp sensor {$ts->name} ({$ts->description}) in alert state. "; 387 | } else if( $ts->currentTemperature >= $ts->criticalThreshold ) { 388 | setStatus( STATUS_CRITICAL ); 389 | $criticals .= "Temp sensor {$ts->name} ({$ts->description}) is >= critical threshold. "; 390 | } else if( $ts->currentTemperature >= $ts->overheatThreshold ) { 391 | setStatus( STATUS_WARNING ); 392 | $criticals .= "Temp sensor {$ts->name} ({$ts->description}) is >= overheat threshold. "; 393 | } 394 | } 395 | 396 | $normals .= " $data. "; 397 | } 398 | 399 | 400 | function checkMemory( $mem ) 401 | { 402 | global $cmdargs, $criticals, $warnings, $unknowns, $normals; 403 | 404 | if( isset( $cmdargs['skip-mem'] ) && $cmdargs['skip-mem'] ) 405 | return; 406 | 407 | $memUtil = sprintf( "%0.2f", (1 - $mem->memFree / $mem->memTotal ) * 100.0 ); 408 | 409 | if( $memUtil > $cmdargs['memcrit'] ) { 410 | setStatus( STATUS_CRITICAL ); 411 | $criticals .= "Memory usage at {$memUtil}%. "; 412 | } else if( $memUtil > $cmdargs['memwarn'] ) { 413 | setStatus( STATUS_WARNING ); 414 | $warnings .= "Memory usage at {$memUtil}%. "; 415 | } else { 416 | $normals .= " Memory OK ({$memUtil}%)."; 417 | } 418 | } 419 | 420 | /** 421 | * Parses (and checks some) command line arguments 422 | */ 423 | function parseArguments() 424 | { 425 | global $checkOptions, $cmdargs, $checksEnabled, $periods, $periodsEnabled, $argc, $argv; 426 | 427 | if( $argc == 1 ) { 428 | printUsage( true ); 429 | exit( STATUS_UNKNOWN ); 430 | } 431 | 432 | $i = 1; 433 | 434 | 435 | while( $i < $argc ) { 436 | 437 | if( $argv[$i][0] != '-' ) { 438 | $i++; 439 | continue; 440 | } 441 | 442 | switch( $argv[$i][1] ) { 443 | 444 | case 'V': 445 | printVersion(); 446 | exit( STATUS_OK ); 447 | break; 448 | 449 | case 'v': 450 | $cmdargs['log_level'] = LOG__VERBOSE; 451 | $i++; 452 | break; 453 | 454 | case 'd': 455 | $cmdargs['log_level'] = LOG__DEBUG; 456 | $i++; 457 | break; 458 | 459 | case 'c': 460 | $cmdargs['api_url'] = $argv[$i+1]; 461 | $i++; 462 | break; 463 | 464 | case 'h': 465 | $cmdargs['host'] = $argv[$i+1]; 466 | $i++; 467 | break; 468 | 469 | case 'u': 470 | $cmdargs['username'] = $argv[$i+1]; 471 | $i++; 472 | break; 473 | 474 | case 'p': 475 | $cmdargs['password'] = $argv[$i+1]; 476 | $i++; 477 | break; 478 | 479 | case 't': 480 | $cmdargs['target'] = $argv[$i+1]; 481 | $i++; 482 | break; 483 | 484 | case '?': 485 | printHelp(); 486 | exit( STATUS_OK ); 487 | break; 488 | 489 | default: 490 | if( !isset( $argv[$i+1] ) || substr( $argv[$i+1], 0, 1 ) == '-' ) 491 | $cmdargs[ substr( $argv[$i], 2 ) ] = true; 492 | else 493 | $cmdargs[ substr( $argv[$i], 2 ) ] = $argv[$i+1]; 494 | 495 | $i++; 496 | break; 497 | } 498 | 499 | } 500 | 501 | } 502 | 503 | 504 | /** 505 | * Sets the planned exit status without overriding a previous error states. 506 | * 507 | * @param int $new_status New status to set. 508 | * @return void 509 | */ 510 | function setStatus( $new_status ) 511 | { 512 | global $status; 513 | 514 | if( $new_status > $status ) 515 | $status = $new_status; 516 | } 517 | 518 | /** 519 | * Prints a given message to stdout (or stderr as appropriate). 520 | * 521 | * @param string $log The log message. 522 | * @param int $level The log level the user has requested. 523 | * @return void 524 | */ 525 | function _log( $log, $level ) 526 | { 527 | global $cmdargs; 528 | 529 | if( $level == LOG__ERROR ) 530 | fwrite( STDERR, "$log\n" ); 531 | else if( $level <= $cmdargs['log_level'] ) 532 | print( $log . "\n" ); 533 | } 534 | 535 | 536 | /** 537 | * Print script usage instructions to the stadout 538 | */ 539 | function printUsage() 540 | { 541 | global $argv; 542 | $progname = basename( $argv[0] ); 543 | 544 | echo << -u -p [-t ] [-V] [-h] [-?] [--help] 546 | 547 | END_USAGE; 548 | 549 | } 550 | 551 | 552 | /** 553 | * Print version information 554 | */ 555 | function printVersion() 556 | { 557 | global $argv; 558 | 559 | printf( basename( $argv[0] ) . " (Nagios Plugin) %s\n", VERSION ); 560 | echo "Licensed under the New BSD License\n\n"; 561 | 562 | echo << -u -p [-V] [-?] [--help] 589 | 590 | Options: 591 | 592 | -?,--help 593 | Print detailed help screen. 594 | -V 595 | Print version information. 596 | -c 597 | API URL 598 | -u 599 | API Username 600 | -p 601 | API Password 602 | -t 603 | Target - omit for all, or one of: 604 | COOLING|POWER|TEMPERATURE|MEMORY|CPU|UPTIME 605 | -v 606 | Verbose output 607 | -d 608 | Debug output 609 | 610 | --skip-mem Skip memory checks 611 | --memwarn Percentage of memory usage for warning (using: 85) 612 | --memcrit Percentage of memory usage for critical (using: 90) 613 | 614 | --skip-temp Skip temperature checks 615 | --skip-fans Skip fan checks 616 | 617 | --skip-psu Skip PSU(s) checks 618 | 619 | --skip-reboot Skip reboot check 620 | 621 | 622 | END_USAGE; 623 | 624 | } 625 | -------------------------------------------------------------------------------- /check_barracuda_lb_active.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # 3 | # check_barracuda_lb_active.pl - nagios plugin 4 | # 5 | # Check if a Barracuda Load Balance in High Avilability mode is active or not. 6 | # 7 | # Ideally, I'd like a warning on failover but I need to monitor a live system 8 | # without test lab. So, for a first pass, I will check of a resource pool IP 9 | # is or is not set on the system. In time, I'd like to check the following MIBs: 10 | # 11 | # IP-MIB::ipAddressCreated.ipv4."x.x.x.x" = Timeticks: (0) 0:00:00.00 12 | # IP-MIB::ipAddressLastChanged.ipv4."x.x.x.x" = Timeticks: (0) 0:00:00.00 13 | # 14 | # which are shown above for a specific IP where no failover has occured since 15 | # boot and where the above MIBs are (at least initially) NOT present on the 16 | # inactive box. 17 | # 18 | # Copyright (c) 2011, Barry O'Donovan 19 | # All rights reserved. 20 | # 21 | # Redistribution and use in source and binary forms, with or without modification, 22 | # are permitted provided that the following conditions are met: 23 | # 24 | # * Redistributions of source code must retain the above copyright notice, this 25 | # list of conditions and the following disclaimer. 26 | # 27 | # * Redistributions in binary form must reproduce the above copyright notice, this 28 | # list of conditions and the following disclaimer in the documentation and/or 29 | # other materials provided with the distribution. 30 | # 31 | # * Neither the name of Open Solutions nor the names of its contributors may be 32 | # used to endorse or promote products derived from this software without 33 | # specific prior written permission. 34 | # 35 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 36 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 37 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 38 | # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 39 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 40 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 41 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 42 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 43 | # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 44 | # OF THE POSSIBILITY OF SUCH DAMAGE. 45 | # 46 | 47 | use strict; 48 | 49 | use Net::SNMP; 50 | use Getopt::Long; 51 | &Getopt::Long::config( 'auto_abbrev' ); 52 | 53 | my %ERRORS = ( 54 | 'UNSET', -1, 55 | 'OK' , 0, 56 | 'WARNING', 1, 57 | 'CRITICAL', 2, 58 | 'UNKNOWN', 3 59 | ); 60 | 61 | my $status; 62 | my $TIMEOUT = 20; 63 | my $state = "UNSET"; 64 | my $answer = ""; 65 | my $snmpkey; 66 | my $community = "public"; 67 | my $port = 161; 68 | my $hostname = undef; 69 | my $session; 70 | my $error; 71 | my $response = undef; 72 | 73 | my $ip = undef; 74 | my $verbose = 0; 75 | my $help = 0; 76 | my $notexpected = 0; 77 | 78 | # Just in case of problems, let's not hang Nagios 79 | $SIG{'ALRM'} = sub { 80 | print( "ERROR: No snmp response from $hostname\n" ); 81 | exit $ERRORS{"UNKNOWN"}; 82 | }; 83 | alarm( $TIMEOUT ); 84 | 85 | 86 | $status = GetOptions( 87 | "hostname=s", \$hostname, 88 | "community=s", \$community, 89 | "port=i", \$port, 90 | "verbose", \$verbose, 91 | "ip=s" , \$ip, 92 | "help|?", \$help, 93 | "inactive", \$notexpected 94 | ); 95 | 96 | if( !$status || $help ) { 97 | usage(); 98 | } 99 | 100 | 101 | usage() if( !defined( $hostname ) || !defined( $ip )); 102 | 103 | ( $session, $error ) = Net::SNMP->session( 104 | -hostname => $hostname, 105 | -community => $community, 106 | -port => $port, 107 | -translate => 0 108 | ); 109 | 110 | if( !defined( $session ) ) 111 | { 112 | $state = 'UNKNOWN'; 113 | $answer = $error; 114 | print( "$state: $answer" ); 115 | exit $ERRORS{$state}; 116 | } 117 | 118 | 119 | my $snmpIPv4AddresIfIndexTable = '.1.3.6.1.2.1.4.34.1.3.1.4'; 120 | 121 | my $ifIndex = snmpGetRequest( $snmpIPv4AddresIfIndexTable . '.' . $ip, 'IPv4 Address If Index' ); 122 | 123 | if( $ifIndex != 0 && $notexpected ) { 124 | &setstate( 'WARNING', "In active state for $ip when expecting inactive state" ); 125 | } elsif( $ifIndex == 0 && !$notexpected ) { 126 | &setstate( 'WARNING', "In inactive state for $ip when expecting active state" ); 127 | } elsif( $ifIndex == 0 ) { 128 | &setstate( 'OK', "In inactive state for $ip" ); 129 | } elsif( $ifIndex != 0 ) { 130 | &setstate( 'OK', "In active state for $ip" ); 131 | } 132 | 133 | $session->close; 134 | 135 | print "$answer\n"; 136 | exit $ERRORS{$state}; 137 | 138 | 139 | 140 | 141 | 142 | sub usage { 143 | printf "Script to check the high availibility state of a Barracuda Load Balancer\n\n"; 144 | printf "check_barracuda_lb_active.pl --community --hostname --ip x.x.x.x\n\n"; 145 | printf "Usage:\n\n"; 146 | printf "Additional options:\n\n"; 147 | printf " --help This help message\n\n"; 148 | printf " --hostname The hostname to check\n"; 149 | printf " --port The port to query SNMP on (using: $port)\n"; 150 | printf " --community The SNMP access community (using: $community)\n\n"; 151 | printf " --ip The IP address to check for the presence of\n\n"; 152 | printf " --inactive You expect NOT to find the IP - confirming inactive state\n\n"; 153 | printf "\nCopyright (c) 2011, Barry O'Donovan \n"; 154 | printf "All rights reserved.\n\n"; 155 | printf "This script comes with ABSOLUTELY NO WARRANTY\n"; 156 | printf "This programm is licensed under the terms of the "; 157 | printf "BSD New License (check source code for details)\n"; 158 | printf "\n\n"; 159 | 160 | exit $ERRORS{"UNKNOWN"} if !$help; 161 | exit 0; 162 | } 163 | 164 | sub setstate { 165 | my $newstate = shift( @_ ); 166 | my $message = shift( @_ ); 167 | 168 | if( $ERRORS{$newstate} > $ERRORS{$state} ) 169 | { 170 | $state = $newstate; 171 | } 172 | elsif( $newstate eq 'UNKNOWN' && $state eq 'OK' ) 173 | { 174 | $state = $newstate; 175 | } 176 | 177 | if( $answer ) { $answer .= "
\n"; } 178 | 179 | $answer .= $message; 180 | } 181 | 182 | sub snmpGetTable { 183 | my $oid = shift( @_ ); 184 | my $check = shift( @_ ); 185 | 186 | if( !defined( $response = $session->get_table( $oid ) ) ) 187 | { 188 | if( $session->error_status() == 2 || $session->error() =~ m/requested table is empty or does not exist/i ) 189 | { 190 | print "OID not supported for $check ($oid).\n" if $verbose; 191 | return 0; 192 | } 193 | 194 | $answer = $session->error(); 195 | $session->close; 196 | 197 | $state = 'CRITICAL'; 198 | print( "$state: $answer (in check for $check with OID: $oid)\n" ); 199 | exit $ERRORS{$state}; 200 | } 201 | 202 | return $response; 203 | } 204 | 205 | sub snmpGetRequest { 206 | my $oid = shift( @_ ); 207 | my $check = shift( @_ ); 208 | my $response; 209 | 210 | if( !defined( $response = $session->get_request( $oid ) ) ) 211 | { 212 | if( $session->error_status() == 2 || $session->error() =~ m/requested table is empty or does not exist/i ) 213 | { 214 | print "OID not supported for $check ($oid).\n" if $verbose; 215 | return 0; 216 | } 217 | 218 | $answer = $session->error(); 219 | $session->close; 220 | 221 | $state = 'CRITICAL'; 222 | print( "$state: $answer (in check for $check with OID: $oid)\n" ); 223 | exit $ERRORS{$state}; 224 | } 225 | 226 | return $response; 227 | } 228 | -------------------------------------------------------------------------------- /check_bgpstatus.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | # 3 | # check_bgpstatus.pl - nagios plugin 4 | # 5 | # Copyright (C) 2018 Nick Hilliard All Rights Reserved 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are 9 | # met: 10 | # 11 | # 1. Redistributions of source code must retain the above copyright notice, 12 | # this list of conditions and the following disclaimer. 13 | # 14 | # 2. Redistributions in binary form must reproduce the above copyright 15 | # notice, this list of conditions and the following disclaimer in the 16 | # documentation and/or other materials provided with the distribution. 17 | # 18 | # 3. Neither the name of the copyright holder nor the names of its 19 | # contributors may be used to endorse or promote products derived from this 20 | # software without specific prior written permission. 21 | # 22 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 23 | # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 24 | # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 26 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | use strict; 35 | use warnings; 36 | 37 | use Net::SNMP; 38 | use Getopt::Long qw(:config pass_through);; 39 | use Data::Dumper; 40 | 41 | use constant { 42 | NAGIOS_OK => 0, 43 | NAGIOS_WARNING => 1, 44 | NAGIOS_CRITICAL => 2, 45 | NAGIOS_UNKNOWN => 3, 46 | }; 47 | 48 | my $err = { 49 | 0 => 'OK', 50 | 1 => 'WARNING', 51 | 2 => 'CRITICAL', 52 | 3 => 'UNKNOWN', 53 | }; 54 | 55 | my $host; 56 | my $debug = 0; 57 | my $community = 'public'; 58 | my $port = 161; 59 | my $timeout = 30; 60 | my $mibtype = undef; 61 | my $snmpversion = '2c'; 62 | my $username = undef; 63 | my $authprotocol = 'sha1'; 64 | my $authpassword = undef; 65 | my $privprotocol = 'aes'; 66 | my $privpassword; 67 | 68 | GetOptions( 69 | 'debug!' => \$debug, 70 | 'host=s' => \$host, 71 | 'community=s' => \$community, 72 | 'port=s' => \$port, 73 | 'timeout=i' => \$timeout, 74 | 'mibtype=s' => \$mibtype, 75 | 'snmpversion=s' => \$snmpversion, 76 | 'username=s' => \$username, 77 | 'authprotocol=s' => \$authprotocol, 78 | 'authpassword=s' => \$authpassword, 79 | 'privprotocol=s' => \$privprotocol, 80 | 'privpassword=s' => \$privpassword, 81 | ); 82 | 83 | if (!$host) { 84 | verboseexit (NAGIOS_CRITICAL, "no hostname provided"); 85 | } 86 | 87 | my $oids = { 88 | 'generic' => { 89 | 'mibidentifier' => '1.3.6.1.2.1.15.2', 90 | 'bgpPeerState' => '1.3.6.1.2.1.15.3.1.2', 91 | 'bgpPeerAdminStatus' => '1.3.6.1.2.1.15.3.1.3', 92 | 'bgpPeerRemoteAs' => '1.3.6.1.2.1.15.3.1.9', 93 | 'bgpPeerLastError' => '1.3.6.1.2.1.15.3.1.14', 94 | }, 95 | 'cisco' => { 96 | 'mibidentifier' => '1.3.6.1.4.1.9.9.187.1.2.5.1.3', 97 | 'bgpPeerState' => '1.3.6.1.4.1.9.9.187.1.2.5.1.3', 98 | 'bgpPeerAdminStatus' => '1.3.6.1.4.1.9.9.187.1.2.5.1.4', 99 | 'bgpPeerRemoteAs' => '1.3.6.1.4.1.9.9.187.1.2.5.1.11', 100 | 'bgpPeerLastError' => '1.3.6.1.4.1.9.9.187.1.2.5.1.17', 101 | }, 102 | 'arista' => { 103 | 'mibidentifier' => '1.3.6.1.4.1.30065.4.1.1.2.1.2', 104 | 'bgpPeerState' => '1.3.6.1.4.1.30065.4.1.1.2.1.13.1', 105 | 'bgpPeerAdminStatus' => '1.3.6.1.4.1.30065.4.1.1.2.1.12.1', 106 | 'bgpPeerRemoteAs' => '1.3.6.1.4.1.30065.4.1.1.2.1.10.1', 107 | 'bgpPeerLastError' => '1.3.6.1.4.1.30065.4.1.1.3.1.1.1', 108 | }, 109 | 'juniper' => { 110 | 'mibidentifier' => '.1.3.6.1.4.1.2636.5.1.1.2.4.3', 111 | 'bgpPeerState' => '.1.3.6.1.4.1.2636.5.1.1.2.1.1.1.2', 112 | 'bgpPeerAdminStatus' => '.1.3.6.1.4.1.2636.5.1.1.2.1.1.1.3', 113 | 'bgpPeerRemoteAs' => '.1.3.6.1.4.1.2636.5.1.1.2.1.1.1.13', 114 | 'bgpPeerLastError' => '.1.3.6.1.4.1.2636.5.1.1.2.2.1.1.2', 115 | }, 116 | }; 117 | 118 | my $bgperrorcodes = { 119 | 1 => 'Message Header Error', 120 | 2 => 'OPEN Message Error', 121 | 3 => 'UPDATE Message Error', 122 | 4 => 'Hold Timer Expired', 123 | 5 => 'Finite State Machine Error', 124 | 6 => 'Cease', 125 | 7 => 'ROUTE-REFRESH Message Error', 126 | }; 127 | 128 | # BGP Error Subcodes 129 | my $bgpsuberrorcodes = { 130 | # Message Header Error subcodes 131 | 1 => { 132 | 1 => 'Connection Not Synchronized', 133 | 2 => 'Bad Message Length', 134 | 3 => 'Bad Message Type', 135 | }, 136 | 137 | # OPEN Message Error subcodes 138 | 2 => { 139 | 1 => 'Unsupported Version Number', 140 | 2 => 'Bad Peer AS', 141 | 3 => 'Bad BGP Identifier', 142 | 4 => 'Unsupported Optional Parameter', 143 | 5 => '[Deprecated]', 144 | 6 => 'Unacceptable Hold Time', 145 | 7 => 'Unsupported Capability', 146 | }, 147 | 148 | # UPDATE Message Error subcodes 149 | 3 => { 150 | 1 => 'Malformed Attribute List', 151 | 2 => 'Unrecognized Well-known Attribute', 152 | 3 => 'Missing Well-known Attribute', 153 | 4 => 'Attribute Flags Error', 154 | 5 => 'Attribute Length Error', 155 | 6 => 'Invalid ORIGIN Attribute', 156 | 7 => '[Deprecated]', 157 | 8 => 'Invalid NEXT_HOP Attribute', 158 | 9 => 'Optional Attribute Error', 159 | 10 => 'Invalid Network Field', 160 | 11 => 'Malformed AS_PATH', 161 | }, 162 | 163 | # BGP Finite State Machine Error Subcodes 164 | 5 => { 165 | 1 => 'Receive Unexpected Message in OpenSent State', 166 | 2 => 'Receive Unexpected Message in OpenConfirm State', 167 | 3 => 'Receive Unexpected Message in Established State', 168 | }, 169 | 170 | # BGP Cease NOTIFICATION message subcodes 171 | 6 => { 172 | 1 => 'Maximum Number of Prefixes Reached', 173 | 2 => 'Administrative Shutdown', 174 | 3 => 'Peer De-configured', 175 | 4 => 'Administrative Reset', 176 | 5 => 'Connection Rejected', 177 | 6 => 'Other Configuration Change', 178 | 7 => 'Connection Collision Resolution', 179 | 8 => 'Out of Resources', 180 | 9 => 'Hard Reset (TEMPORARY - registered 2017-04-21, expires 2018-04-21) [draft-ietf-idr-bgp-gr-notification]' 181 | }, 182 | 183 | # BGP ROUTE-REFRESH Message Error subcodes 184 | 7 => { 185 | 1 => 'Invalid Message Length', 186 | }, 187 | }; 188 | 189 | sub bgplasterror { 190 | my ($bgperror) = @_; 191 | 192 | my $lasterror = hex($bgperror); 193 | my $errcode = ($lasterror & 0xff00) >> 8; 194 | my $errsubcode = ($lasterror & 0xff); 195 | 196 | my $errtext; 197 | 198 | if (defined ($bgperrorcodes->{$errcode})) { 199 | $errtext = $bgperrorcodes->{$errcode}; 200 | } 201 | if (defined ($bgpsuberrorcodes->{$errcode}->{$errsubcode})) { 202 | $errtext .= ": ".$bgpsuberrorcodes->{$errcode}->{$errsubcode} 203 | } 204 | 205 | return $errtext; 206 | } 207 | 208 | $SIG{'ALRM'} = sub { 209 | verboseexit (NAGIOS_CRITICAL, "SNMP response timeout for $host"); 210 | }; 211 | alarm($timeout); 212 | 213 | sub verboseexit { 214 | my ($errval, $notice) = @_; 215 | 216 | print $err->{$errval}.": $notice\n"; 217 | exit $errval; 218 | } 219 | 220 | 221 | sub hexstringtoipv6 { 222 | my ($ipaddr) = @_; 223 | 224 | # The following operation could have been done in a 225 | # single statement, but it would have been 226 | # incomprehensible. 227 | 228 | # The ipv6 address is encoded as a string of 229 | # dot-separated 8-bit digits. We use split() to 230 | # convert this into an array. map() is then used to 231 | # execute sprintf ('%02x') on each element of the 232 | # array. These two operations convert the data from 233 | # an array of 8-bit integers into an array of 8-bit 234 | # hex strings. We concatenate these with join, 235 | # which results in a 32-char hex string. 236 | 237 | my $hexadddr = join ('', map (sprintf ('%02x', $_), split (/\./, $ipaddr))); 238 | 239 | # This statement splits the 32-char hex string into 240 | # an array of 8 groups of 4 hex chars. These are 241 | # joined with a ':' token to form an ipv6 address in 242 | # long format. 243 | 244 | $hexadddr = join (':', unpack("(A4)*", $hexadddr)); 245 | 246 | # Rather than writing code to convert this to ipv6 247 | # short format, we take a short cut with Net::IP. 248 | 249 | use Net::IP; 250 | my $ip = new Net::IP ($hexadddr); 251 | 252 | $ipaddr = $ip->short(); 253 | 254 | return ($ipaddr); 255 | } 256 | 257 | sub decodeip { 258 | my ($mibtype, $baseoid, $response) = @_; 259 | my $ipaddr = undef; 260 | 261 | if ($mibtype eq 'generic') { 262 | $response =~ s/^($baseoid)\.//; 263 | return undef unless ($response =~ /^(\d+\.\d+\.\d+\.\d+)/); 264 | $ipaddr = $1; 265 | } elsif ($mibtype eq 'cisco' || $mibtype eq 'arista') { 266 | # remove first part of OID response 267 | $response =~ s/^($baseoid)\.//; 268 | 269 | # format is .n.m.addr, where n = protocol version and m = encoding length 270 | return undef unless ($response =~ /^(\d+\.\d+)\.(.*)/); 271 | if ($1 eq '1.4') { # AFI ipv4, 4 byte address 272 | $ipaddr = $2; 273 | } elsif ($1 eq '2.16') { # AFI ipv6, 16 byte address 274 | $ipaddr = hexstringtoipv6 ($2); 275 | } 276 | } elsif ($mibtype eq 'juniper') { 277 | $response =~ s/^($baseoid)\.//; 278 | # format is .r.n.laddr.n.raddr, where r = rib and n = protocol version. We want raddr. 279 | 280 | # strip off RIB identifier 281 | $response =~ s/^\d+\.//; 282 | 283 | return undef unless ($response =~ /^([12])\.(.*)/); 284 | if ($1 eq '1') { # AFI ipv4 285 | $response =~ /\.1\.(\d+(\.\d+){3})$/; 286 | $ipaddr = $1; 287 | } elsif ($1 eq '2') { # AFI ipv6 288 | $response =~ /\.2\.(\d+(\.\d+){15})$/; 289 | $ipaddr = hexstringtoipv6 ($1); 290 | } 291 | } 292 | 293 | return $ipaddr; 294 | } 295 | 296 | my @sessionargs = ( 297 | hostname => $host, 298 | port => $port, 299 | version => $snmpversion, 300 | ); 301 | 302 | if ($snmpversion eq '3') { 303 | push @sessionargs, ( 304 | username => $username, 305 | authprotocol => $authprotocol, 306 | authpassword => $authpassword, 307 | privprotocol => $privprotocol, 308 | privpassword => $privpassword, 309 | ); 310 | } else { 311 | push @sessionargs, ( 312 | community => $community, 313 | ); 314 | } 315 | 316 | my ($snmpsession, $error) = Net::SNMP->session(@sessionargs); 317 | 318 | if (!defined($snmpsession)) { 319 | verboseexit (NAGIOS_UNKNOWN, $error); 320 | } 321 | 322 | if (defined ($mibtype) && !defined ($oids->{$mibtype})) { 323 | verboseexit (NAGIOS_UNKNOWN, "undefined mibtype specified on command line"); 324 | } 325 | 326 | if (!defined ($mibtype)) { 327 | foreach my $mibcandidate (keys %{$oids}) { 328 | next if ($mibcandidate eq 'generic'); 329 | my $response = $snmpsession->get_table($oids->{$mibcandidate}->{'mibidentifier'}); 330 | if (defined ($response)) { 331 | $mibtype = $mibcandidate; 332 | last; 333 | } 334 | } 335 | } 336 | 337 | $mibtype = 'generic' unless (defined ($mibtype)); 338 | 339 | my $state; 340 | foreach my $oid (keys %{$oids->{$mibtype}}) { 341 | next if ($oid eq 'mibidentifier'); 342 | 343 | $debug && print STDERR "checking OID $oid\n"; 344 | my $response = $snmpsession->get_table($oids->{$mibtype}->{$oid}); 345 | if (!defined ($response)) { 346 | my $sessionerror = $snmpsession->error; 347 | $snmpsession->close; 348 | verboseexit (NAGIOS_CRITICAL, "$host: $sessionerror: $oid"); 349 | } 350 | 351 | foreach my $responseoid (keys %{$response}) { 352 | my $ipaddr = decodeip ($mibtype, $oids->{$mibtype}->{$oid}, $responseoid); 353 | $state->{$oid}->{$ipaddr} = $response->{$responseoid}; 354 | } 355 | } 356 | 357 | $snmpsession->close; 358 | 359 | $debug && print STDERR Dumper ($state); 360 | 361 | my $shutdown = 0; 362 | my $inactive = 0; 363 | my $established = 0; 364 | my @warnings; 365 | 366 | foreach my $ip (keys %{$state->{bgpPeerAdminStatus}}) { 367 | if ($state->{bgpPeerAdminStatus}->{$ip} == 1) { 368 | $shutdown++; 369 | } elsif ($state->{bgpPeerState}->{$ip} == 6) { 370 | $established++ 371 | } else { 372 | $inactive++; 373 | my $errtext = bgplasterror($state->{bgpPeerLastError}->{$ip}); 374 | my $lasterror = hex($state->{bgpPeerLastError}->{$ip}); 375 | my $errcode = ($lasterror & 0xff00) >> 8; 376 | my $errsubcode = ($lasterror & 0xff); 377 | my $peerwarning = sprintf ("ip: $ip, asn: ".$state->{bgpPeerRemoteAs}->{$ip}.", errcode: $errcode, subcode: $errsubcode"); 378 | if (defined($errtext)) { 379 | $peerwarning .= sprintf (", text: $errtext"); 380 | } 381 | push @warnings, $peerwarning; 382 | } 383 | } 384 | 385 | $debug && print STDERR Dumper (@warnings); 386 | 387 | my $errval = $inactive ? NAGIOS_WARNING : NAGIOS_OK; 388 | my $peertext = ''; 389 | if (@warnings) { 390 | $peertext = " (".join ("/", @warnings).")"; 391 | } 392 | 393 | verboseexit ($errval, "host '$host', sessions up: $established, down: $inactive, shutdown: $shutdown".$peertext ); 394 | 395 | __END__ 396 | 397 | @output = `$whois -T aut-num AS$bgpStatus{$key}{$snmpbgpPeerRemoteAs}`; 398 | -------------------------------------------------------------------------------- /check_chassis_brocade.php: -------------------------------------------------------------------------------- 1 | #! /usr/bin/php 2 | 51 | * @author The Skilled Team of PHP Developers at Open Solutions 52 | */ 53 | 54 | date_default_timezone_set('Europe/Dublin'); 55 | define( "VERSION", '1.0.0' ); 56 | 57 | ini_set( 'max_execution_time', '55' ); 58 | 59 | ini_set( 'display_errors', true ); 60 | ini_set( 'display_startup_errors', true ); 61 | 62 | define( "STATUS_OK", 0 ); 63 | define( "STATUS_WARNING", 1 ); 64 | define( "STATUS_CRITICAL", 2 ); 65 | define( "STATUS_UNKNOWN", 3 ); 66 | 67 | define( "LOG__NONE", 0 ); 68 | define( "LOG__ERROR", 1 ); 69 | define( "LOG__VERBOSE", 2 ); 70 | define( "LOG__DEBUG", 3 ); 71 | 72 | // initialise some variables 73 | $status = STATUS_OK; 74 | $log_level = LOG__NONE; 75 | 76 | 77 | // possible output strings 78 | $criticals = ""; 79 | $warnings = ""; 80 | $unknowns = ""; 81 | $normals = ""; 82 | 83 | // set default values for command line arguments 84 | $cmdargs = [ 85 | 'port' => '161', 86 | 'log_level' => LOG__NONE, 87 | 'memwarn' => 80, 88 | 'memcrit' => 90, 89 | 'reboot' => 3600, 90 | 'thres-cpu-1sec' => '95,98', 91 | 'thres-cpu-5sec' => '85,95', 92 | 'thres-cpu-1min' => '70,90' 93 | ]; 94 | 95 | 96 | // parse the command line arguments 97 | parseArguments(); 98 | 99 | 100 | //print_r( $cmdargs ); die(); 101 | 102 | require 'OSS_SNMP/OSS_SNMP/SNMP.php'; 103 | 104 | $snmp = new \OSS_SNMP\SNMP( $cmdargs['host'], $cmdargs['community'] ); 105 | 106 | checkCPU(); 107 | checkReboot(); 108 | checkPower(); 109 | checkFans(); 110 | checkTemperature(); 111 | checkMemory(); 112 | checkOthers(); 113 | 114 | 115 | if( $status == STATUS_OK ) 116 | $msg = "OK -{$normals}\n"; 117 | else 118 | $msg = "{$criticals}{$warnings}{$unknowns}\n"; 119 | 120 | echo $msg; 121 | exit( $status ); 122 | 123 | 124 | 125 | /** 126 | * Checks the chassis temperature 127 | * 128 | */ 129 | function checkTemperature() 130 | { 131 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 132 | 133 | if( isset( $cmdargs['skip-temp'] ) && $cmdargs['skip-temp'] ) 134 | return; 135 | 136 | _log( "========== Temperature check start ==========", LOG__DEBUG ); 137 | 138 | try 139 | { 140 | // remember - Foundry use units of 0.5 Celcius: 141 | $temp = $snmp->useFoundry_Chassis()->actualTemperature() / 2.0; 142 | $warn = $snmp->useFoundry_Chassis()->warningTemperature() / 2.0; 143 | $shut = $snmp->useFoundry_Chassis()->shutdownTemperature() / 2.0; 144 | 145 | if( !$warn ) $warn = 64.0; 146 | } 147 | catch( OSS_SNMP\Exception $e ) 148 | { 149 | /* Temp not supported 150 | setStatus( STATUS_UNKNOWN ); 151 | $unknowns .= "Temperature unknown - possibly not supported on platform? Use --skip-temp. "; 152 | _log( "WARNING: Temperature unknown - possibly not supported on platform? Use --skip-temp.\n", LOG__ERROR ); 153 | */ 154 | return; 155 | } 156 | 157 | _log( "Temp: $temp (Warn: $warn Shutdown: $shut)", LOG__VERBOSE ); 158 | $tempdata = sprintf( "Temp (A/W/C): %0.1f/%0.1f/%0.1f", $temp, $warn, $shut ); 159 | 160 | if( $temp >= $warn ) 161 | { 162 | setStatus( STATUS_CRITICAL ); 163 | $criticals .= "Temperature approaching SHUTDOWN threshold: $temp/$shut"; 164 | } 165 | 166 | if( isset( $cmdargs['tempcrit'] ) && $cmdargs['tempcrit'] && $temp >= $cmdargs['tempcrit'] ) 167 | { 168 | setStatus( STATUS_CRITICAL ); 169 | $criticals .= "Temperature exceeds critical threshold: $temp/" . $cmdargs['tempcrit']; 170 | } 171 | else if( isset( $cmdargs['tempwarn'] ) && $cmdargs['tempwarn'] && $temp >= $cmdargs['tempwarn'] ) 172 | { 173 | setStatus( STATUS_WARNING ); 174 | $warnings .= "Temperature exceeds warning threshold: $temp/" . $cmdargs['tempwarn']; 175 | } 176 | 177 | $normals .= " $tempdata."; 178 | 179 | _log( "========== Temperature check end ==========\n", LOG__DEBUG ); 180 | } 181 | 182 | 183 | function checkFans() 184 | { 185 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 186 | 187 | if( isset( $cmdargs['skip-fans'] ) && $cmdargs['skip-fans'] ) 188 | return; 189 | 190 | _log( "========== Fan check start ==========", LOG__DEBUG ); 191 | 192 | try 193 | { 194 | $fanDescs = $snmp->useFoundry_Chassis()->fanDescriptions(); 195 | $fanStates = $snmp->useFoundry_Chassis()->fanStates(); 196 | } 197 | catch( OSS_SNMP\Exception $e ) 198 | { 199 | setStatus( STATUS_UNKNOWN ); 200 | $unknowns .= "Fan states unknown - possibly not supported on platform? Use --skip-fans. "; 201 | _log( "WARNING: Fan states unknown - possibly not supported on platform? Use --skip-fans.\n", LOG__ERROR ); 202 | return; 203 | } 204 | 205 | $fandata = 'Fans:'; 206 | 207 | foreach( $fanStates as $i => $state ) 208 | { 209 | _log( "Fan: {$fanDescs[$i]} - $state", LOG__VERBOSE ); 210 | $fandata .= $state == OSS_SNMP\MIBS\Foundry\Chassis::FAN_STATE_NORMAL ? ' OK' : " " . strtoupper( $state ); 211 | 212 | if( $state == OSS_SNMP\MIBS\Foundry\Chassis::FAN_STATE_FAILURE ) 213 | { 214 | setStatus( STATUS_CRITICAL ); 215 | $criticals .= "Fan state for {$fanDescs[$i]}: $state"; 216 | } 217 | else if( $state != OSS_SNMP\MIBS\Foundry\Chassis::FAN_STATE_NORMAL ) 218 | { 219 | setStatus( STATUS_WARNING ); 220 | $criticals .= "Fan state for {$fanDescs[$i]}: $state"; 221 | } 222 | } 223 | 224 | $normals .= " $fandata."; 225 | 226 | _log( "========== Fan check end ==========\n", LOG__DEBUG ); 227 | } 228 | 229 | 230 | 231 | function checkPower() 232 | { 233 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 234 | 235 | if( isset( $cmdargs['skip-psu'] ) && $cmdargs['skip-psu'] ) 236 | return; 237 | 238 | _log( "========== PSU check start ==========", LOG__DEBUG ); 239 | 240 | try 241 | { 242 | $psuDescs = $snmp->useFoundry_Chassis()->psuDescriptions(); 243 | $psuStates = $snmp->useFoundry_Chassis()->psuStates(); 244 | } 245 | catch( OSS_SNMP\Exception $e ) 246 | { 247 | setStatus( STATUS_UNKNOWN ); 248 | $unknowns .= "PSU states unknown - possibly not supported on platform? Use --skip-psu. "; 249 | _log( "WARNING: PSU states unknown - possibly not supported on platform? Use --skip-psu.\n", LOG__ERROR ); 250 | return; 251 | } 252 | 253 | $psudata = 'PSUs:'; 254 | 255 | foreach( $psuStates as $i => $state ) 256 | { 257 | _log( "PSU: {$psuDescs[$i]} - $state", LOG__VERBOSE ); 258 | $psudata .= $state == OSS_SNMP\MIBS\Foundry\Chassis::PSU_STATE_NORMAL ? ' OK' : " " . strtoupper( $state ); 259 | 260 | if( $state == OSS_SNMP\MIBS\Foundry\Chassis::PSU_STATE_FAILURE ) 261 | { 262 | setStatus( STATUS_CRITICAL ); 263 | $criticals .= "PSU state for {$psuDescs[$i]}: $state"; 264 | } 265 | else if( $state != OSS_SNMP\MIBS\Foundry\Chassis::PSU_STATE_NORMAL ) 266 | { 267 | setStatus( STATUS_WARNING ); 268 | $criticals .= "PSU state for {$psuDescs[$i]}: $state"; 269 | } 270 | } 271 | 272 | $normals .= " $psudata."; 273 | 274 | _log( "========== PSU check end ==========\n", LOG__DEBUG ); 275 | } 276 | 277 | 278 | 279 | function checkMemory() 280 | { 281 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 282 | 283 | if( isset( $cmdargs['skip-mem'] ) && $cmdargs['skip-mem'] ) 284 | return; 285 | 286 | _log( "========== Memory check start ==========", LOG__DEBUG ); 287 | 288 | $memUtil = $snmp->useFoundry_Chassis()->memoryUtilisation(); 289 | 290 | _log( "Memory used: {$memUtil}%", LOG__VERBOSE ); 291 | 292 | if( $memUtil > $cmdargs['memcrit'] ) 293 | { 294 | setStatus( STATUS_CRITICAL ); 295 | $criticals .= "Memory usage at {$memUtil}%. "; 296 | } 297 | else if( $memUtil > $cmdargs['memwarn'] ) 298 | { 299 | setStatus( STATUS_WARNING ); 300 | $warnings .= "Memory usage at {$memUtil}%. "; 301 | } 302 | else 303 | $normals .= " Memory OK ({$memUtil}%)."; 304 | 305 | _log( "========== Memory check end ==========\n", LOG__DEBUG ); 306 | } 307 | 308 | 309 | function checkReboot() 310 | { 311 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 312 | 313 | if( isset( $cmdargs['skip-reboot'] ) && $cmdargs['skip-reboot'] ) 314 | return; 315 | 316 | _log( "========== Reboot check start ==========", LOG__DEBUG ); 317 | 318 | // uptime in seconds 319 | $sysuptime = $snmp->useSystem()->uptime() / 100.0; 320 | 321 | if( ( isset( $cmdargs['lastcheck'] ) && $cmdargs['lastcheck'] && $sysuptime <= $cmdargs['lastcheck'] ) 322 | || ( $sysuptime < $cmdargs['reboot'] ) ) 323 | { 324 | // Brocade use a 32bit integer for sysuptime (argh!) so it rolls over every 497.1 days 325 | // If we find that the system has rebooted, we'll get a second opinion 326 | 327 | $engineTime = $snmp->useSNMP_Engine()->time(); 328 | 329 | if( ( isset( $cmdargs['lastcheck'] ) && $cmdargs['lastcheck'] && $engineTime <= $cmdargs['lastcheck'] ) 330 | || ( $engineTime < $cmdargs['reboot'] ) ) 331 | { 332 | setStatus( STATUS_CRITICAL ); 333 | $criticals .= sprintf( "Device rebooted %0.1f minutes ago. ", $sysuptime / 60.0 ); 334 | } 335 | } 336 | 337 | _log( "========== Reboot check end ==========", LOG__DEBUG ); 338 | } 339 | 340 | 341 | 342 | function checkCPU() 343 | { 344 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 345 | 346 | if( isset( $cmdargs['skip-cpu'] ) && $cmdargs['skip-cpu'] ) 347 | return; 348 | 349 | _log( "========== CPU check start ==========", LOG__DEBUG ); 350 | 351 | $cpudata = 'CPU: '; 352 | 353 | foreach( [ '1sec', '5sec', '1min' ] as $period ) 354 | { 355 | if( isset( $cmdargs["skip-cpu-$period"] ) && $cmdargs["skip-cpu-$period"] ) 356 | continue; 357 | 358 | $fn = "cpu{$period}Utilisation"; 359 | $util = $snmp->useFoundry_Chassis()->$fn(); 360 | 361 | _log( "CPU: $period - $util%", LOG__VERBOSE ); 362 | $cpudata .= " $period $util%"; 363 | 364 | list( $w, $c ) = explode( ',', $cmdargs["thres-cpu-$period"] ); 365 | 366 | if( $util >= $c ) 367 | { 368 | setStatus( STATUS_CRITICAL ); 369 | $criticals .= "CPU $period usage at {$util}%. "; 370 | } 371 | else if( $util >= $w ) 372 | { 373 | setStatus( STATUS_WARNING ); 374 | $warnings .= "CPU $period usage at {$util}%. "; 375 | } 376 | } 377 | 378 | $normals .= " $cpudata."; 379 | } 380 | 381 | 382 | 383 | function checkOthers() 384 | { 385 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 386 | 387 | if( isset( $cmdargs['skip-others'] ) && $cmdargs['skip-others'] ) 388 | return; 389 | 390 | _log( "========== Others check start ==========", LOG__DEBUG ); 391 | 392 | try 393 | { 394 | if( $snmp->useFoundry_Chassis()->isQueueOverflow() ) 395 | { 396 | _log( "Error - queue overflow indicated", LOG__VERBOSE ); 397 | setStatus( STATUS_CRITICAL ); 398 | $criticals .= "Queue overflow indicated. "; 399 | } 400 | else 401 | _log( "OK - queue overflow not indicated", LOG__VERBOSE ); 402 | } 403 | catch( \OSS_SNMP\Exception $e ) 404 | { /* not supported on this platform */ } 405 | 406 | try 407 | { 408 | if( $snmp->useFoundry_Chassis()->isBufferShortage() ) 409 | { 410 | _log( "Error - buffer shortage indicated", LOG__VERBOSE ); 411 | setStatus( STATUS_CRITICAL ); 412 | $criticals .= "Buffer shortage indicated. "; 413 | } 414 | else 415 | _log( "OK - buffer shortage not indicated", LOG__VERBOSE ); 416 | } 417 | catch( \OSS_SNMP\Exception $e ) 418 | { /* not supported on this platform */ } 419 | 420 | try 421 | { 422 | if( $snmp->useFoundry_Chassis()->isDMAFailure() ) 423 | { 424 | _log( "Error - DMA failure indicated", LOG__VERBOSE ); 425 | setStatus( STATUS_CRITICAL ); 426 | $criticals .= "DMA failure indicated. "; 427 | } 428 | else 429 | _log( "OK - DMA failure not indicated", LOG__VERBOSE ); 430 | } 431 | catch( \OSS_SNMP\Exception $e ) 432 | { /* not supported on this platform */ } 433 | 434 | try 435 | { 436 | if( $snmp->useFoundry_Chassis()->isResourceLow() ) 437 | { 438 | _log( "Error - low resources indicated", LOG__VERBOSE ); 439 | setStatus( STATUS_CRITICAL ); 440 | $criticals .= "Low resources indicated. "; 441 | } 442 | else 443 | _log( "OK - low resources not indicated", LOG__VERBOSE ); 444 | } 445 | catch( \OSS_SNMP\Exception $e ) 446 | { /* not supported on this platform */ } 447 | 448 | try 449 | { 450 | if( $snmp->useFoundry_Chassis()->isExcessiveError() ) 451 | { 452 | _log( "Error - excessive errors indicated", LOG__VERBOSE ); 453 | setStatus( STATUS_CRITICAL ); 454 | $criticals .= "Excessive errors indicated. "; 455 | } 456 | else 457 | _log( "OK - excessive errors not indicated", LOG__VERBOSE ); 458 | } 459 | catch( \OSS_SNMP\Exception $e ) 460 | { /* not supported on this platform */ } 461 | 462 | _log( "========== Others check end ==========", LOG__DEBUG ); 463 | } 464 | 465 | 466 | /** 467 | * Parses (and checks some) command line arguments 468 | */ 469 | function parseArguments() 470 | { 471 | global $checkOptions, $cmdargs, $checksEnabled, $periods, $periodsEnabled, $argc, $argv; 472 | 473 | if( $argc == 1 ) 474 | { 475 | printUsage( true ); 476 | exit( STATUS_UNKNOWN ); 477 | } 478 | 479 | $i = 1; 480 | 481 | 482 | while( $i < $argc ) 483 | { 484 | if( $argv[$i][0] != '-' ) 485 | { 486 | $i++; 487 | continue; 488 | } 489 | 490 | switch( $argv[$i][1] ) 491 | { 492 | 493 | case 'V': 494 | printVersion(); 495 | exit( STATUS_OK ); 496 | break; 497 | 498 | case 'v': 499 | $cmdargs['log_level'] = LOG__VERBOSE; 500 | $i++; 501 | break; 502 | 503 | case 'd': 504 | $cmdargs['log_level'] = LOG__DEBUG; 505 | $i++; 506 | break; 507 | 508 | case 'c': 509 | $cmdargs['community'] = $argv[$i+1]; 510 | $i++; 511 | break; 512 | 513 | case 'h': 514 | $cmdargs['host'] = $argv[$i+1]; 515 | $i++; 516 | break; 517 | 518 | case 'p': 519 | $cmdargs['port'] = $argv[$i+1]; 520 | $i++; 521 | break; 522 | 523 | case '?': 524 | printHelp(); 525 | exit( STATUS_OK ); 526 | break; 527 | 528 | default: 529 | if( !isset( $argv[$i+1] ) || substr( $argv[$i+1], 0, 1 ) == '-' ) 530 | $cmdargs[ substr( $argv[$i], 2 ) ] = true; 531 | else 532 | $cmdargs[ substr( $argv[$i], 2 ) ] = $argv[$i+1]; 533 | 534 | $i++; 535 | break; 536 | } 537 | 538 | } 539 | 540 | } 541 | 542 | 543 | /** 544 | * Sets the planned exit status without overriding a previous error states. 545 | * 546 | * @param int $new_status New status to set. 547 | * @return void 548 | */ 549 | function setStatus( $new_status ) 550 | { 551 | global $status; 552 | 553 | if( $new_status > $status ) 554 | $status = $new_status; 555 | } 556 | 557 | /** 558 | * Prints a given message to stdout (or stderr as appropriate). 559 | * 560 | * @param string $log The log message. 561 | * @param int $level The log level the user has requested. 562 | * @return void 563 | */ 564 | function _log( $log, $level ) 565 | { 566 | global $cmdargs; 567 | 568 | if( $level == LOG__ERROR ) 569 | fwrite( STDERR, "$log\n" ); 570 | else if( $level <= $cmdargs['log_level'] ) 571 | print( $log . "\n" ); 572 | } 573 | 574 | 575 | /** 576 | * Print script usage instructions to the stadout 577 | */ 578 | function printUsage() 579 | { 580 | global $argv; 581 | $progname = basename( $argv[0] ); 582 | 583 | echo << -p -h [-V] [-h] [-?] [--help] 585 | 586 | END_USAGE; 587 | 588 | } 589 | 590 | 591 | /** 592 | * Print version information 593 | */ 594 | function printVersion() 595 | { 596 | global $argv; 597 | 598 | printf( basename( $argv[0] ) . " (Nagios Plugin) %s\n", VERSION ); 599 | echo "Licensed under the New BSD License\n\n"; 600 | 601 | echo << -p -h [-V] [-?] [--help] 628 | 629 | Options: 630 | 631 | -?,--help 632 | Print detailed help screen. 633 | -V 634 | Print version information. 635 | -c 636 | SNMP Community (public) 637 | -h 638 | Device to poll 639 | -p 640 | SNMP port (default 161) 641 | -v 642 | Verbose output 643 | -d 644 | Debug output 645 | 646 | --skip-mem Skip memory checks 647 | --memwarn Percentage of memory usage for warning (using: 70) 648 | --memcrit Percentage of memory usage for critical (using: 90) 649 | 650 | --skip-temp Skip temperature checks 651 | --tempwarn Degrees Celsius for warning (in addition to device's setting) 652 | --tempcrit Degrees Celsius for critical (in addition to device's setting) 653 | --skip-fans Skip fan checks 654 | 655 | --skip-psu Skip PSU(s) checks 656 | --ignore-psu-notpresent Ignore PSUs that are not installed 657 | 658 | --skip-reboot Skip reboot check 659 | --lastcheck Nagios $LASTSERVICECHECK$ macro. Used by reboot check such that if the 660 | last reboot was within the last check, then an alert if generated. Overrides 661 | --reboot to ensure reboots are caught 662 | 663 | --skip-others Skip 'other' checks 664 | 665 | --skip-cpu Skip all CPU utilisation checks 666 | --skip-cpu-1sec Skip 1sec CPU utilisation check 667 | --skip-cpu-5sec Skip 5sec CPU utilisation check 668 | --skip-cpu-1min Skip 1min CPU utilisation check 669 | --thres-cpu-1sec CPU warning,critical thresholds for 1sec checks (using 95,98) 670 | --thres-cpu-5sec CPU warning,critical thresholds for 5sec checks (using 85,95) 671 | --thres-cpu-1min CPU warning,critical thresholds for 1min checks (using 70,90) 672 | 673 | --reboot How many minutes ago should we warn that the device has been rebooted (using: 60) 674 | 675 | 676 | END_USAGE; 677 | 678 | } 679 | 680 | -------------------------------------------------------------------------------- /check_chassis_extreme.php: -------------------------------------------------------------------------------- 1 | #! /usr/bin/php 2 | 51 | */ 52 | 53 | date_default_timezone_set('Europe/Dublin'); 54 | define( "VERSION", '1.0.0' ); 55 | 56 | ini_set( 'max_execution_time', '55' ); 57 | 58 | ini_set( 'display_errors', true ); 59 | ini_set( 'display_startup_errors', true ); 60 | 61 | define( "STATUS_OK", 0 ); 62 | define( "STATUS_WARNING", 1 ); 63 | define( "STATUS_CRITICAL", 2 ); 64 | define( "STATUS_UNKNOWN", 3 ); 65 | 66 | define( "LOG__NONE", 0 ); 67 | define( "LOG__ERROR", 1 ); 68 | define( "LOG__VERBOSE", 2 ); 69 | define( "LOG__DEBUG", 3 ); 70 | 71 | // initialise some variables 72 | $status = STATUS_OK; 73 | $log_level = LOG__NONE; 74 | 75 | 76 | // possible output strings 77 | $criticals = ""; 78 | $warnings = ""; 79 | $unknowns = ""; 80 | $normals = ""; 81 | 82 | // set default values for command line arguments 83 | $cmdargs = [ 84 | 'port' => '161', 85 | 'log_level' => LOG__NONE, 86 | 'memwarn' => 80, 87 | 'memcrit' => 90, 88 | 'tempwarn' => 55, 89 | 'tempcrit' => 65, 90 | 'reboot' => 3600, 91 | 'thres-cpu' => '85,95', 92 | ]; 93 | 94 | 95 | // parse the command line arguments 96 | parseArguments(); 97 | 98 | 99 | //print_r( $cmdargs ); die(); 100 | 101 | require 'OSS_SNMP/OSS_SNMP/SNMP.php'; 102 | 103 | $snmp = new \OSS_SNMP\SNMP( $cmdargs['host'], $cmdargs['community'] ); 104 | 105 | checkCPU(); 106 | checkReboot(); 107 | checkPower(); 108 | checkFans(); 109 | checkTemperature(); 110 | checkMemory(); 111 | 112 | 113 | if( $status == STATUS_OK ) 114 | $msg = "OK -{$normals}\n"; 115 | else 116 | $msg = "{$criticals}{$warnings}{$unknowns}\n"; 117 | 118 | echo $msg; 119 | exit( $status ); 120 | 121 | 122 | 123 | /** 124 | * Checks the chassis temperature 125 | * 126 | */ 127 | function checkTemperature() 128 | { 129 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 130 | 131 | if( isset( $cmdargs['skip-temp'] ) && $cmdargs['skip-temp'] ) 132 | return; 133 | 134 | _log( "========== Temperature check start ==========", LOG__DEBUG ); 135 | 136 | try 137 | { 138 | $temp = $snmp->useExtreme_System_Common()->currentTemperature(); 139 | $over = $snmp->useExtreme_System_Common()->overTemperatureAlarm(); 140 | } catch( OSS_SNMP\Exception $e ) { 141 | setStatus( STATUS_UNKNOWN ); 142 | $unknowns .= "Temperature unknown - possibly not supported on platform? Use --skip-temp. "; 143 | _log( "WARNING: Temperature unknown - possibly not supported on platform? Use --skip-temp.\n", LOG__ERROR ); 144 | return; 145 | } 146 | 147 | _log( "Temp: {$temp}'C", LOG__VERBOSE ); 148 | _log( "Over temp alert: " . ( $over ? 'YES' : 'NO' ), LOG__VERBOSE ); 149 | 150 | $tempdata = sprintf( "Temp: %d'C", $temp ); 151 | 152 | if( $over ) { 153 | setStatus( STATUS_CRITICAL ); 154 | $criticals .= "Temperature alarm set: {$temp}'C. "; 155 | } 156 | 157 | if( isset( $cmdargs['tempcrit'] ) && $cmdargs['tempcrit'] && $temp >= $cmdargs['tempcrit'] ) 158 | { 159 | setStatus( STATUS_CRITICAL ); 160 | $criticals .= "Temperature exceeds critical threshold: $temp/" . $cmdargs['tempcrit']; 161 | } 162 | else if( isset( $cmdargs['tempwarn'] ) && $cmdargs['tempwarn'] && $temp >= $cmdargs['tempwarn'] ) 163 | { 164 | setStatus( STATUS_WARNING ); 165 | $warnings .= "Temperature exceeds warning threshold: $temp/" . $cmdargs['tempwarn']; 166 | } 167 | 168 | $normals .= " $tempdata."; 169 | 170 | _log( "========== Temperature check end ==========\n", LOG__DEBUG ); 171 | } 172 | 173 | 174 | function checkFans() 175 | { 176 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 177 | 178 | if( isset( $cmdargs['skip-fans'] ) && $cmdargs['skip-fans'] ) 179 | return; 180 | 181 | _log( "========== Fan check start ==========", LOG__DEBUG ); 182 | 183 | try 184 | { 185 | $fans = $snmp->useExtreme_System_Common()->fanOperational(); 186 | $speeds = $snmp->useExtreme_System_Common()->fanSpeed(); 187 | 188 | } catch( OSS_SNMP\Exception $e ) { 189 | setStatus( STATUS_UNKNOWN ); 190 | $unknowns .= "Fan states unknown - possibly not supported on platform? Use --skip-fans. "; 191 | _log( "WARNING: Fan states unknown - possibly not supported on platform? Use --skip-fans.\n", LOG__ERROR ); 192 | return; 193 | } 194 | 195 | $fandata = 'Fans:'; 196 | 197 | foreach( $fans as $i => $operational ) 198 | { 199 | $ok = $operational && $speeds[$i] >= 2000; 200 | 201 | _log( "Fan: {$i} - " . ( $ok ? 'OK' : 'NOT OK' ) . " ({$speeds[$i]} RPM)", LOG__VERBOSE ); 202 | $fandata .= " [{$i} - " . ( $ok ? 'OK' : 'NOT OK' ) . " ({$speeds[$i]} RPM)];"; 203 | 204 | if( !$ok ) { 205 | setStatus( STATUS_CRITICAL ); 206 | if( $operational && $speeds[$i] < 2000 ) 207 | $criticals .= "Fan {$i} is operational but speed is outside normal operating range (<2000). "; 208 | else if( !$operational ) 209 | $criticals .= "Fan {$i} is not operational. "; 210 | else 211 | $criticals .= "Fan {$i} is not operational (reason unknown). "; 212 | } 213 | } 214 | 215 | $normals .= " $fandata."; 216 | 217 | _log( "========== Fan check end ==========\n", LOG__DEBUG ); 218 | } 219 | 220 | 221 | 222 | function checkPower() 223 | { 224 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 225 | 226 | if( isset( $cmdargs['skip-psu'] ) && $cmdargs['skip-psu'] ) 227 | return; 228 | 229 | _log( "========== PSU check start ==========", LOG__DEBUG ); 230 | 231 | try 232 | { 233 | $psuStates = $snmp->useExtreme_System_Common()->powerSupplyStatus(); 234 | $psuSerials = $snmp->useExtreme_System_Common()->powerSupplySerialNumbers(); 235 | $psuSources = $snmp->useExtreme_System_Common()->powerSupplySource(); 236 | 237 | $sources = OSS_SNMP\MIBS\Extreme\System\Common::$POWER_SUPPLY_SOURCES; 238 | $states = OSS_SNMP\MIBS\Extreme\System\Common::$POWER_SUPPLY_STATES; 239 | 240 | $systemPowerState = $snmp->useExtreme_System_Common()->systemPowerState(); 241 | $systemState = OSS_SNMP\MIBS\Extreme\System\Common::$POWER_STATES; 242 | } 243 | catch( OSS_SNMP\Exception $e ) 244 | { 245 | setStatus( STATUS_UNKNOWN ); 246 | $unknowns .= "PSU states unknown - possibly not supported on platform? Use --skip-psu. "; 247 | _log( "WARNING: PSU states unknown - possibly not supported on platform? Use --skip-psu.\n", LOG__ERROR ); 248 | return; 249 | } 250 | 251 | $psudata = 'PSUs:'; 252 | 253 | foreach( $psuStates as $i => $state ) 254 | { 255 | _log( "PSU: {$i} - {$states[$state]} (Serial: {$psuSerials[$i]}; Source: {$sources[ $psuSources[$i] ]})", LOG__VERBOSE ); 256 | $psudata .= " {$i} - {$states[$state]};"; 257 | 258 | if( $state == OSS_SNMP\MIBS\Extreme\System\Common::POWER_SUPPLY_STATUS_NOT_PRESENT 259 | && !( isset( $cmdargs['ignore-psu-notpresent'] ) && $cmdargs['ignore-psu-notpresent'] ) ) 260 | { 261 | setStatus( STATUS_WARNING ); 262 | $warnings .= "PSU $i is not present"; 263 | } 264 | else if( $state != OSS_SNMP\MIBS\Extreme\System\Common::POWER_SUPPLY_STATUS_PRESENT_OK ) 265 | { 266 | setStatus( STATUS_CRITICAL ); 267 | $criticals .= "PSU state for {$i}: {$states[$state]}"; 268 | } 269 | } 270 | 271 | $psudata .= ". "; 272 | 273 | if( $systemPowerState == OSS_SNMP\MIBS\Extreme\System\Common::SYSTEM_POWER_STATE_REDUNDANT_POWER_AVAILABLE ) 274 | { 275 | $psudata .= "Overall system power state: redundant power available"; 276 | } 277 | else if( $systemPowerState == OSS_SNMP\MIBS\Extreme\System\Common::SYSTEM_POWER_STATE_SUFFICIENT_BUT_NOT_REDUNDANT_POWER ) 278 | { 279 | setStatus( STATUS_WARNING ); 280 | $warnings .= "Overall system power state: sufficient but not redundant power available"; 281 | } 282 | else if( $systemPowerState == OSS_SNMP\MIBS\Extreme\System\Common::SYSTEM_POWER_STATE_INSUFFICIENT_POWER ) 283 | { 284 | setStatus( STATUS_CRITICAL ); 285 | $warnings .= "Overall system power state: insufficent power available"; 286 | } 287 | 288 | $normals .= " $psudata."; 289 | 290 | _log( "========== PSU check end ==========\n", LOG__DEBUG ); 291 | } 292 | 293 | 294 | 295 | function checkMemory() 296 | { 297 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 298 | 299 | if( isset( $cmdargs['skip-mem'] ) && $cmdargs['skip-mem'] ) 300 | return; 301 | 302 | _log( "========== Memory check start ==========", LOG__DEBUG ); 303 | 304 | $memUtil = $snmp->useExtreme_SwMonitor_Memory()->percentUsage(); 305 | 306 | $memData = " Memory (slot:usage%):"; 307 | 308 | foreach( $memUtil as $slotId => $usage ) { 309 | _log( "Memory used in slot {$slotId}: {$usage}%", LOG__VERBOSE ); 310 | 311 | if( $usage > $cmdargs['memcrit'] ) 312 | { 313 | setStatus( STATUS_CRITICAL ); 314 | $criticals .= "Memory usage in slot {$slotId} at {$usage}%. "; 315 | } 316 | else if( $usage > $cmdargs['memwarn'] ) 317 | { 318 | setStatus( STATUS_WARNING ); 319 | $warningss .= "Memory usage in slot {$slotId} at {$usage}%. "; 320 | } 321 | else 322 | $memData .= " {$slotId}:{$usage}%"; 323 | } 324 | $normals .= $memData . '. '; 325 | 326 | _log( "========== Memory check end ==========\n", LOG__DEBUG ); 327 | } 328 | 329 | 330 | function checkReboot() 331 | { 332 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 333 | 334 | if( isset( $cmdargs['skip-reboot'] ) && $cmdargs['skip-reboot'] ) 335 | return; 336 | 337 | _log( "========== Reboot check start ==========", LOG__DEBUG ); 338 | 339 | $bootTime = $snmp->useExtreme_System_Common()->bootTime(); 340 | 341 | 342 | if( ( isset( $cmdargs['lastcheck'] ) && $cmdargs['lastcheck'] && $bootTime <= $cmdargs['lastcheck'] ) 343 | || ( time() - $bootTime <= $cmdargs['reboot'] ) ) 344 | { 345 | setStatus( STATUS_CRITICAL ); 346 | $criticals .= sprintf( "Device rebooted %0.1f minutes ago. ", ( time() - $bootTime ) / 60.0 ); 347 | } 348 | 349 | $up = ( time() - $bootTime ) / 60.0 / 60.0; 350 | 351 | if( $up < 24 ) 352 | $up = sprintf( "Uptime: %0.1f hours. ", $up ); 353 | else 354 | $up = sprintf( "Uptime: %0.1f days. ", $up / 24 ); 355 | 356 | _log( "Last reboot: " . ( ( time() - $bootTime ) / 60.0 ) . " minutes ago", LOG__VERBOSE ); 357 | _log( $up, LOG__VERBOSE ); 358 | 359 | $normals .= " {$up}"; 360 | 361 | _log( "========== Reboot check end ==========", LOG__DEBUG ); 362 | } 363 | 364 | 365 | 366 | function checkCPU() 367 | { 368 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 369 | 370 | if( isset( $cmdargs['skip-cpu'] ) && $cmdargs['skip-cpu'] ) 371 | return; 372 | 373 | _log( "========== CPU check start ==========", LOG__DEBUG ); 374 | 375 | $util = $snmp->useExtreme_SwMonitor_Cpu()->totalUtilization(); 376 | 377 | 378 | _log( "CPU: 5sec - $util%", LOG__VERBOSE ); 379 | $cpudata = "CPU: 5sec - {$util}%"; 380 | 381 | list( $w, $c ) = explode( ',', $cmdargs["thres-cpu"] ); 382 | 383 | if( $util >= $c ) 384 | { 385 | setStatus( STATUS_CRITICAL ); 386 | $criticals .= "CPU 5sec usage at {$util}%. "; 387 | } 388 | else if( $util >= $w ) 389 | { 390 | setStatus( STATUS_WARNING ); 391 | $warnings .= "CPU 5sec usage at {$util}%. "; 392 | } 393 | 394 | $normals .= " $cpudata."; 395 | } 396 | 397 | 398 | 399 | /** 400 | * Parses (and checks some) command line arguments 401 | */ 402 | function parseArguments() 403 | { 404 | global $checkOptions, $cmdargs, $checksEnabled, $periods, $periodsEnabled, $argc, $argv; 405 | 406 | if( $argc == 1 ) 407 | { 408 | printUsage( true ); 409 | exit( STATUS_UNKNOWN ); 410 | } 411 | 412 | $i = 1; 413 | 414 | 415 | while( $i < $argc ) 416 | { 417 | if( $argv[$i][0] != '-' ) 418 | { 419 | $i++; 420 | continue; 421 | } 422 | 423 | switch( $argv[$i][1] ) 424 | { 425 | 426 | case 'V': 427 | printVersion(); 428 | exit( STATUS_OK ); 429 | break; 430 | 431 | case 'v': 432 | $cmdargs['log_level'] = LOG__VERBOSE; 433 | $i++; 434 | break; 435 | 436 | case 'd': 437 | $cmdargs['log_level'] = LOG__DEBUG; 438 | $i++; 439 | break; 440 | 441 | case 'c': 442 | if( !isset( $argv[$i+1] ) ) { printUsage( true ); exit( STATUS_UNKNOWN ); } 443 | $cmdargs['community'] = $argv[$i+1]; 444 | $i++; 445 | break; 446 | 447 | case 'h': 448 | if( !isset( $argv[$i+1] ) ) { printUsage( true ); exit( STATUS_UNKNOWN ); } 449 | $cmdargs['host'] = $argv[$i+1]; 450 | $i++; 451 | break; 452 | 453 | case 'p': 454 | if( !isset( $argv[$i+1] ) ) { printUsage( true ); exit( STATUS_UNKNOWN ); } 455 | $cmdargs['port'] = $argv[$i+1]; 456 | $i++; 457 | break; 458 | 459 | case '?': 460 | printHelp(); 461 | exit( STATUS_OK ); 462 | break; 463 | 464 | default: 465 | if( !isset( $argv[$i+1] ) || substr( $argv[$i+1], 0, 1 ) == '-' ) 466 | $cmdargs[ substr( $argv[$i], 2 ) ] = true; 467 | else 468 | $cmdargs[ substr( $argv[$i], 2 ) ] = $argv[$i+1]; 469 | 470 | $i++; 471 | break; 472 | } 473 | 474 | } 475 | 476 | } 477 | 478 | 479 | /** 480 | * Sets the planned exit status without overriding a previous error states. 481 | * 482 | * @param int $new_status New status to set. 483 | * @return void 484 | */ 485 | function setStatus( $new_status ) 486 | { 487 | global $status; 488 | 489 | if( $new_status > $status ) 490 | $status = $new_status; 491 | } 492 | 493 | /** 494 | * Prints a given message to stdout (or stderr as appropriate). 495 | * 496 | * @param string $log The log message. 497 | * @param int $level The log level the user has requested. 498 | * @return void 499 | */ 500 | function _log( $log, $level ) 501 | { 502 | global $cmdargs; 503 | 504 | if( $level == LOG__ERROR ) 505 | fwrite( STDERR, "$log\n" ); 506 | else if( $level <= $cmdargs['log_level'] ) 507 | print( $log . "\n" ); 508 | } 509 | 510 | 511 | /** 512 | * Print script usage instructions to the stadout 513 | */ 514 | function printUsage() 515 | { 516 | global $argv; 517 | $progname = basename( $argv[0] ); 518 | 519 | echo << -p -h [-V] [-h] [-?] [--help] 521 | 522 | END_USAGE; 523 | 524 | } 525 | 526 | 527 | /** 528 | * Print version information 529 | */ 530 | function printVersion() 531 | { 532 | global $argv; 533 | 534 | printf( basename( $argv[0] ) . " (Nagios Plugin) %s\n", VERSION ); 535 | echo "Licensed under the New BSD License\n\n"; 536 | 537 | echo << -p -h [-V] [-?] [--help] 564 | 565 | Options: 566 | 567 | -?,--help 568 | Print detailed help screen. 569 | -V 570 | Print version information. 571 | -c 572 | SNMP Community (public) 573 | -h 574 | Device to poll 575 | -p 576 | SNMP port (default 161) 577 | -v 578 | Verbose output 579 | -d 580 | Debug output 581 | 582 | --skip-mem Skip memory checks 583 | --memwarn Percentage of memory usage for warning (using: {$cmdargs['memwarn']}) 584 | --memcrit Percentage of memory usage for critical (using: {$cmdargs['memcrit']}) 585 | 586 | --skip-temp Skip temperature checks 587 | --tempwarn Degrees Celsius for warning (using: {$cmdargs['tempwarn']}) 588 | --tempcrit Degrees Celsius for critical (using: {$cmdargs['tempwarn']}) 589 | --skip-fans Skip fan checks 590 | 591 | --skip-psu Skip PSU(s) checks 592 | --ignore-psu-notpresent Ignore PSUs that are not installed 593 | 594 | --skip-reboot Skip reboot check 595 | --lastcheck Nagios $LASTSERVICECHECK$ macro. Used by reboot check such that if the 596 | last reboot was within the last check, then an alert is generated. Overrides 597 | --reboot to ensure reboots are caught 598 | --reboot How many seconds ago should we warn that the device has been rebooted (using: {$cmdargs['reboot']}) 599 | 600 | --skip-cpu Skip all CPU utilisation checks 601 | --thres-cpu CPU warning,critical thresholds for 5sec checks (using {$cmdargs['thres-cpu']}) 602 | 603 | 604 | END_USAGE; 605 | 606 | } 607 | -------------------------------------------------------------------------------- /check_chassis_juniper_mx204.php: -------------------------------------------------------------------------------- 1 | #! /usr/bin/php 2 | 53 | */ 54 | 55 | date_default_timezone_set('Europe/Dublin'); 56 | define( "VERSION", '1.0.0' ); 57 | 58 | ini_set( 'max_execution_time', '55' ); 59 | 60 | ini_set( 'display_errors', true ); 61 | ini_set( 'display_startup_errors', true ); 62 | 63 | define( "STATUS_OK", 0 ); 64 | define( "STATUS_WARNING", 1 ); 65 | define( "STATUS_CRITICAL", 2 ); 66 | define( "STATUS_UNKNOWN", 3 ); 67 | 68 | define( "LOG__NONE", 0 ); 69 | define( "LOG__ERROR", 1 ); 70 | define( "LOG__VERBOSE", 2 ); 71 | define( "LOG__DEBUG", 3 ); 72 | 73 | // initialise some variables 74 | $status = STATUS_OK; 75 | $log_level = LOG__NONE; 76 | 77 | 78 | // possible output strings 79 | $criticals = ""; 80 | $warnings = ""; 81 | $unknowns = ""; 82 | $normals = ""; 83 | 84 | // set default values for command line arguments 85 | $cmdargs = [ 86 | 'port' => '161', 87 | 'log_level' => LOG__NONE, 88 | 'memwarn' => 80, 89 | 'memcrit' => 90, 90 | 'tempwarn' => 55, 91 | 'tempcrit' => 65, 92 | 'reboot' => 3600, 93 | 'thres-cpu' => '85,95', 94 | 'target' => null, 95 | ]; 96 | 97 | 98 | // parse the command line arguments 99 | parseArguments(); 100 | 101 | 102 | //print_r( $cmdargs ); die(); 103 | 104 | require 'OSS_SNMP/OSS_SNMP/SNMP.php'; 105 | 106 | $snmp = new \OSS_SNMP\SNMP( $cmdargs['host'], $cmdargs['community'] ); 107 | 108 | // FANS|POWER|TEMPERATURE|MEMORY|CPU|UPTIME 109 | 110 | if( $cmdargs['target'] === null || $cmdargs['target'] == 'CPU' ) 111 | checkCPU(); 112 | 113 | if( $cmdargs['target'] === null || $cmdargs['target'] == 'UPTIME' ) 114 | checkReboot(); 115 | 116 | if( $cmdargs['target'] === null || $cmdargs['target'] == 'POWER' ) 117 | checkPower(); 118 | 119 | if( $cmdargs['target'] === null || $cmdargs['target'] == 'FANS' ) 120 | checkFans(); 121 | 122 | if( $cmdargs['target'] === null || $cmdargs['target'] == 'TEMPERATURE' ) 123 | checkTemperature(); 124 | 125 | if( $cmdargs['target'] === null || $cmdargs['target'] == 'MEMORY' ) 126 | checkMemory(); 127 | 128 | 129 | if( $status == STATUS_OK ) 130 | $msg = "OK -{$normals}\n"; 131 | else 132 | $msg = "{$criticals}{$warnings}{$unknowns}\n"; 133 | 134 | echo $msg; 135 | exit( $status ); 136 | 137 | 138 | 139 | /** 140 | * Checks the chassis temperature 141 | * 142 | */ 143 | function checkTemperature() 144 | { 145 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 146 | 147 | if( isset( $cmdargs['skip-temp'] ) && $cmdargs['skip-temp'] ) 148 | return; 149 | 150 | _log( "========== Temp check start ==========", LOG__DEBUG ); 151 | 152 | // https://oidref.com/1.3.6.1.4.1.2636.3.1.15.1.8 153 | 154 | $fruNames = $snmp->realWalk( 'iso.3.6.1.4.1.2636.3.1.15.1.5' ); 155 | 156 | foreach( $fruNames as $oid => $name ) { 157 | 158 | $oids = explode( '.', $oid ); 159 | $noid = $oids[13] . '.' . $oids[14] . '.' . $oids[15]; 160 | 161 | $fruNames[ $noid ] = $snmp->parseSnmpValue( $name ); 162 | unset( $fruNames[$oid]); 163 | } 164 | 165 | $fruTemps = $snmp->realWalk( 'iso.3.6.1.4.1.2636.3.1.15.1.9' ); 166 | 167 | foreach( $fruTemps as $oid => $name ) { 168 | 169 | $oids = explode( '.', $oid ); 170 | $noid = $oids[13] . '.' . $oids[14] . '.' . $oids[15]; 171 | 172 | $fruTemps[ $noid ] = $snmp->parseSnmpValue( $name ); 173 | unset( $fruTemps[$oid]); 174 | } 175 | 176 | $tempdata = 'Temp sensors:'; 177 | 178 | foreach( $fruTemps as $i => $temp ) 179 | { 180 | if( !$temp ) { 181 | continue; 182 | } 183 | 184 | $ok = ($temp < 65 ); 185 | 186 | _log( "Temp: {$fruNames[$i]} - " . $temp . 'C', LOG__VERBOSE ); 187 | $tempdata .= " [$fruNames[$i] - " . $temp . 'C' . "]"; 188 | 189 | if( !$ok ) { 190 | setStatus( STATUS_CRITICAL ); 191 | $criticals .= "Temp {$fruNames[$i]} is {$state}C - check thresholds and ensure this is okay! "; 192 | } 193 | } 194 | 195 | $normals .= " $tempdata."; 196 | 197 | _log( "========== Temperature check end ==========\n", LOG__DEBUG ); 198 | } 199 | 200 | 201 | function checkFans() 202 | { 203 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 204 | 205 | if( isset( $cmdargs['skip-fans'] ) && $cmdargs['skip-fans'] ) 206 | return; 207 | 208 | _log( "========== Fan check start ==========", LOG__DEBUG ); 209 | 210 | // https://oidref.com/1.3.6.1.4.1.2636.3.1.15.1.8 211 | 212 | $fanNames = $snmp->realWalk( 'iso.3.6.1.4.1.2636.3.1.15.1.5.4' ); 213 | 214 | foreach( $fanNames as $oid => $name ) { 215 | $fanNames[ substr( $oid, -5 ) ] = $snmp->parseSnmpValue( $name ); 216 | unset( $fanNames[$oid]); 217 | } 218 | 219 | $fanStates = $snmp->realWalk( 'iso.3.6.1.4.1.2636.3.1.15.1.8.4' ); 220 | 221 | foreach( $fanStates as $oid => $name ) { 222 | $fanStates[ substr( $oid, -5 ) ] = $snmp->parseSnmpValue( $name ); 223 | unset( $fanStates[$oid]); 224 | } 225 | 226 | $states = [ 227 | 1 => 'unknown(1)', 228 | 2 => 'empty(2)', 229 | 3 => 'present(3)', 230 | 4 => 'ready(4)', 231 | 5 => 'announceOnline(5)', 232 | 6 => 'online(6)', 233 | 7 => 'anounceOffline(7)', 234 | 8 => 'offline(8)', 235 | 9 => 'diagnostic(9)', 236 | 10 => 'standby(10)', 237 | ]; 238 | 239 | $fandata = 'Fans:'; 240 | 241 | foreach( $fanStates as $i => $state ) 242 | { 243 | $ok = $state == 6 ? true : false; 244 | 245 | _log( "Fan: {$fanNames[$i]} - " . $states[$state], LOG__VERBOSE ); 246 | $fandata .= " [$fanNames[$i] - " . $states[$state] . "]"; 247 | 248 | if( !$ok ) { 249 | switch( $state ) { 250 | case 7: 251 | case 8: 252 | setStatus( STATUS_CRITICAL ); 253 | $criticals .= "Fan {$fanNames[$i]} is {$states[$state]}. "; 254 | break; 255 | default: 256 | setStatus( STATUS_WARNING ); 257 | $warnings .= "Fan {$fanNames[$i]} is {$states[$state]}. "; 258 | break; 259 | } 260 | } 261 | } 262 | 263 | $normals .= " $fandata."; 264 | 265 | _log( "========== Fan check end ==========\n", LOG__DEBUG ); 266 | } 267 | 268 | 269 | 270 | function checkPower() 271 | { 272 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 273 | 274 | if( isset( $cmdargs['skip-psu'] ) && $cmdargs['skip-psu'] ) 275 | return; 276 | 277 | _log( "========== PSU check start ==========", LOG__DEBUG ); 278 | 279 | // https://oidref.com/1.3.6.1.4.1.2636.3.1.15.1.8 280 | 281 | // PEM - power entry module 282 | $pemNames = $snmp->realWalk( 'iso.3.6.1.4.1.2636.3.1.15.1.5.2' ); 283 | 284 | foreach( $pemNames as $oid => $name ) { 285 | $pemNames[ substr( $oid, -5 ) ] = $snmp->parseSnmpValue( $name ); 286 | unset( $pemNames[$oid]); 287 | } 288 | 289 | $pemStates = $snmp->realWalk( 'iso.3.6.1.4.1.2636.3.1.15.1.8.2' ); 290 | 291 | foreach( $pemStates as $oid => $name ) { 292 | $pemStates[ substr( $oid, -5 ) ] = $snmp->parseSnmpValue( $name ); 293 | unset( $pemStates[$oid]); 294 | } 295 | 296 | $states = [ 297 | 1 => 'unknown(1)', 298 | 2 => 'empty(2)', 299 | 3 => 'present(3)', 300 | 4 => 'ready(4)', 301 | 5 => 'announceOnline(5)', 302 | 6 => 'online(6)', 303 | 7 => 'anounceOffline(7)', 304 | 8 => 'offline(8)', 305 | 9 => 'diagnostic(9)', 306 | 10 => 'standby(10)', 307 | ]; 308 | 309 | $psudata = 'PSUs:'; 310 | 311 | foreach( $pemStates as $i => $state ) 312 | { 313 | $ok = $state == 6 ? true : false; 314 | 315 | _log( "PSU: {$pemNames[$i]} - " . $states[$state], LOG__VERBOSE ); 316 | $psudata .= " [$pemNames[$i] - " . $states[$state] . "]"; 317 | 318 | if( !$ok ) { 319 | switch( $state ) { 320 | case 7: 321 | case 8: 322 | setStatus( STATUS_CRITICAL ); 323 | $criticals .= "{SU} {$pemNames[$i]} is {$states[$state]}. "; 324 | break; 325 | default: 326 | setStatus( STATUS_WARNING ); 327 | $warnings .= "PSU {$pemNames[$i]} is {$states[$state]}. "; 328 | break; 329 | } 330 | } 331 | } 332 | 333 | $normals .= " $psudata."; 334 | 335 | 336 | _log( "========== PSU check end ==========\n", LOG__DEBUG ); 337 | } 338 | 339 | 340 | 341 | function checkMemory() 342 | { 343 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 344 | 345 | if( isset( $cmdargs['skip-mem'] ) && $cmdargs['skip-mem'] ) 346 | return; 347 | 348 | _log( "========== Memory check start ==========", LOG__DEBUG ); 349 | 350 | $memUtil = $snmp->get('1.3.6.1.4.1.2636.3.1.13.1.27.9.1.0.0'); 351 | 352 | $memData = " Memory (usage%):"; 353 | 354 | if( $memUtil > $cmdargs['memcrit'] ) 355 | { 356 | setStatus( STATUS_CRITICAL ); 357 | $criticals .= "Memory usage at {$memUtil}%. "; 358 | } 359 | else if( $memUtil > $cmdargs['memwarn'] ) 360 | { 361 | setStatus( STATUS_WARNING ); 362 | $warningss .= "Memory usage at {$memUtil}%. "; 363 | } 364 | else 365 | { 366 | $memData .= " {$memUtil}%"; 367 | } 368 | 369 | $normals .= $memData . '. '; 370 | 371 | _log( "========== Memory check end ==========\n", LOG__DEBUG ); 372 | } 373 | 374 | 375 | function checkReboot() 376 | { 377 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 378 | 379 | if( isset( $cmdargs['skip-reboot'] ) && $cmdargs['skip-reboot'] ) 380 | return; 381 | 382 | _log( "========== Reboot check start ==========", LOG__DEBUG ); 383 | 384 | $bootTimeSecs = $snmp->useJuniper()->bootTime() / 100; 385 | 386 | 387 | if( ( isset( $cmdargs['lastcheck'] ) && $cmdargs['lastcheck'] && $bootTimeSecs <= $cmdargs['lastcheck'] ) 388 | || ( $bootTimeSecs <= $cmdargs['reboot'] ) ) 389 | { 390 | setStatus( STATUS_CRITICAL ); 391 | $criticals .= sprintf( "Device rebooted %0.1f minutes ago. ", ( $bootTimeSecs / 60.0 ) ); 392 | } 393 | 394 | $up = $bootTimeSecs / 60.0 / 60.0; 395 | 396 | if( $up < 24 ) 397 | $up = sprintf( "Uptime: %0.1f hours. ", $up ); 398 | else 399 | $up = sprintf( "Uptime: %0.1f days. ", $up / 24 ); 400 | 401 | _log( "Last reboot: " . ( $bootTimeSecs / 60.0 ) . " minutes ago", LOG__VERBOSE ); 402 | _log( $up, LOG__VERBOSE ); 403 | 404 | $normals .= " {$up}"; 405 | 406 | _log( "========== Reboot check end ==========", LOG__DEBUG ); 407 | } 408 | 409 | 410 | 411 | function checkCPU() 412 | { 413 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 414 | 415 | if( isset( $cmdargs['skip-cpu'] ) && $cmdargs['skip-cpu'] ) 416 | return; 417 | 418 | _log( "========== CPU check start ==========", LOG__DEBUG ); 419 | 420 | $util1m = $snmp->useJuniper()->loadAverage1min(); 421 | $util5m = $snmp->useJuniper()->loadAverage5min(); 422 | $util15m = $snmp->useJuniper()->loadAverage15min(); 423 | 424 | _log( "CPU: 1min - $util1m%; 5min - $util5m%; 15min - $util15m%; ", LOG__VERBOSE ); 425 | $cpudata = "CPU: 1min - $util1m%; 5min - $util5m%; 15min - $util15m%"; 426 | 427 | list( $w, $c ) = explode( ',', $cmdargs["thres-cpu"] ); 428 | 429 | if( $util5m >= $c ) 430 | { 431 | setStatus( STATUS_CRITICAL ); 432 | $criticals .= "CPU 5min usage at {$util}%. "; 433 | } 434 | else if( $util5m >= $w ) 435 | { 436 | setStatus( STATUS_WARNING ); 437 | $warnings .= "CPU 5min usage at {$util}%. "; 438 | } 439 | 440 | $normals .= " $cpudata."; 441 | } 442 | 443 | 444 | 445 | /** 446 | * Parses (and checks some) command line arguments 447 | */ 448 | function parseArguments() 449 | { 450 | global $checkOptions, $cmdargs, $checksEnabled, $periods, $periodsEnabled, $argc, $argv; 451 | 452 | if( $argc == 1 ) 453 | { 454 | printUsage( true ); 455 | exit( STATUS_UNKNOWN ); 456 | } 457 | 458 | $i = 1; 459 | 460 | 461 | while( $i < $argc ) 462 | { 463 | if( $argv[$i][0] != '-' ) 464 | { 465 | $i++; 466 | continue; 467 | } 468 | 469 | switch( $argv[$i][1] ) 470 | { 471 | 472 | case 'V': 473 | printVersion(); 474 | exit( STATUS_OK ); 475 | break; 476 | 477 | case 'v': 478 | $cmdargs['log_level'] = LOG__VERBOSE; 479 | $i++; 480 | break; 481 | 482 | case 'd': 483 | $cmdargs['log_level'] = LOG__DEBUG; 484 | $i++; 485 | break; 486 | 487 | case 'c': 488 | if( !isset( $argv[$i+1] ) ) { printUsage( true ); exit( STATUS_UNKNOWN ); } 489 | $cmdargs['community'] = $argv[$i+1]; 490 | $i++; 491 | break; 492 | 493 | case 't': 494 | if( !isset( $argv[$i+1] ) ) { printUsage( true ); exit( STATUS_UNKNOWN ); } 495 | $cmdargs['target'] = $argv[$i+1]; 496 | $i++; 497 | break; 498 | 499 | case 'h': 500 | if( !isset( $argv[$i+1] ) ) { printUsage( true ); exit( STATUS_UNKNOWN ); } 501 | $cmdargs['host'] = $argv[$i+1]; 502 | $i++; 503 | break; 504 | 505 | case 'p': 506 | if( !isset( $argv[$i+1] ) ) { printUsage( true ); exit( STATUS_UNKNOWN ); } 507 | $cmdargs['port'] = $argv[$i+1]; 508 | $i++; 509 | break; 510 | 511 | case '?': 512 | printHelp(); 513 | exit( STATUS_OK ); 514 | break; 515 | 516 | default: 517 | if( !isset( $argv[$i+1] ) || substr( $argv[$i+1], 0, 1 ) == '-' ) 518 | $cmdargs[ substr( $argv[$i], 2 ) ] = true; 519 | else 520 | $cmdargs[ substr( $argv[$i], 2 ) ] = $argv[$i+1]; 521 | 522 | $i++; 523 | break; 524 | } 525 | 526 | } 527 | 528 | } 529 | 530 | 531 | /** 532 | * Sets the planned exit status without overriding a previous error states. 533 | * 534 | * @param int $new_status New status to set. 535 | * @return void 536 | */ 537 | function setStatus( $new_status ) 538 | { 539 | global $status; 540 | 541 | if( $new_status > $status ) 542 | $status = $new_status; 543 | } 544 | 545 | /** 546 | * Prints a given message to stdout (or stderr as appropriate). 547 | * 548 | * @param string $log The log message. 549 | * @param int $level The log level the user has requested. 550 | * @return void 551 | */ 552 | function _log( $log, $level ) 553 | { 554 | global $cmdargs; 555 | 556 | if( $level == LOG__ERROR ) 557 | fwrite( STDERR, "$log\n" ); 558 | else if( $level <= $cmdargs['log_level'] ) 559 | print( $log . "\n" ); 560 | } 561 | 562 | 563 | /** 564 | * Print script usage instructions to the stadout 565 | */ 566 | function printUsage() 567 | { 568 | global $argv; 569 | $progname = basename( $argv[0] ); 570 | 571 | echo << -p -h [-V] [-h] [-?] [--help] 573 | 574 | END_USAGE; 575 | 576 | } 577 | 578 | 579 | /** 580 | * Print version information 581 | */ 582 | function printVersion() 583 | { 584 | global $argv; 585 | 586 | printf( basename( $argv[0] ) . " (Nagios Plugin) %s\n", VERSION ); 587 | echo "Licensed under the New BSD License\n\n"; 588 | 589 | echo << -p -h [-V] [-?] [--help] 616 | 617 | Options: 618 | 619 | -?,--help 620 | Print detailed help screen. 621 | -V 622 | Print version information. 623 | -c 624 | SNMP Community (public) 625 | -h 626 | Device to poll 627 | -t 628 | Target - omit for all, or one of: 629 | FANS|POWER|TEMPERATURE|MEMORY|CPU|UPTIME 630 | -p 631 | SNMP port (default 161) 632 | -v 633 | Verbose output 634 | -d 635 | Debug output 636 | 637 | --skip-mem Skip memory checks 638 | --memwarn Percentage of memory usage for warning (using: {$cmdargs['memwarn']}) 639 | --memcrit Percentage of memory usage for critical (using: {$cmdargs['memcrit']}) 640 | 641 | --skip-temp Skip temperature checks 642 | --tempwarn Degrees Celsius for warning (using: {$cmdargs['tempwarn']}) 643 | --tempcrit Degrees Celsius for critical (using: {$cmdargs['tempwarn']}) 644 | --skip-fans Skip fan checks 645 | 646 | --skip-psu Skip PSU(s) checks 647 | --ignore-psu-notpresent Ignore PSUs that are not installed 648 | 649 | --skip-reboot Skip reboot check 650 | --lastcheck Nagios $LASTSERVICECHECK$ macro. Used by reboot check such that if the 651 | last reboot was within the last check, then an alert is generated. Overrides 652 | --reboot to ensure reboots are caught 653 | --reboot How many seconds ago should we warn that the device has been rebooted (using: {$cmdargs['reboot']}) 654 | 655 | --skip-cpu Skip all CPU utilisation checks 656 | --thres-cpu CPU warning,critical thresholds for 5sec checks (using {$cmdargs['thres-cpu']}) 657 | 658 | 659 | END_USAGE; 660 | 661 | } 662 | -------------------------------------------------------------------------------- /check_chassis_mikrotik.php: -------------------------------------------------------------------------------- 1 | #! /usr/bin/php 2 | 53 | */ 54 | 55 | date_default_timezone_set('Europe/Dublin'); 56 | define( "VERSION", '1.0.0' ); 57 | 58 | ini_set( 'max_execution_time', '55' ); 59 | 60 | ini_set( 'display_errors', true ); 61 | ini_set( 'display_startup_errors', true ); 62 | 63 | define( "STATUS_OK", 0 ); 64 | define( "STATUS_WARNING", 1 ); 65 | define( "STATUS_CRITICAL", 2 ); 66 | define( "STATUS_UNKNOWN", 3 ); 67 | 68 | define( "LOG__NONE", 0 ); 69 | define( "LOG__ERROR", 1 ); 70 | define( "LOG__VERBOSE", 2 ); 71 | define( "LOG__DEBUG", 3 ); 72 | 73 | // initialise some variables 74 | $status = STATUS_OK; 75 | $log_level = LOG__NONE; 76 | 77 | 78 | // possible output strings 79 | $criticals = ""; 80 | $warnings = ""; 81 | $unknowns = ""; 82 | $normals = ""; 83 | 84 | // set default values for command line arguments 85 | $cmdargs = [ 86 | 'port' => '161', 87 | 'log_level' => LOG__NONE, 88 | 'memwarn' => 80, 89 | 'memcrit' => 90, 90 | 'diskwarn' => 80, 91 | 'diskcrit' => 90, 92 | 'tempwarn' => 55, 93 | 'tempcrit' => 65, 94 | 'reboot' => 3600, 95 | 'thres-cpu' => '85,95', 96 | 'target' => null, 97 | ]; 98 | 99 | 100 | // parse the command line arguments 101 | parseArguments(); 102 | 103 | 104 | //print_r( $cmdargs ); die(); 105 | 106 | require 'OSS_SNMP/OSS_SNMP/SNMP.php'; 107 | 108 | $snmp = new \OSS_SNMP\SNMP( $cmdargs['host'], $cmdargs['community'] ); 109 | 110 | // FANS|POWER|TEMPERATURE|MEMORY|CPU|UPTIME|DISK 111 | 112 | if( $cmdargs['target'] === null || $cmdargs['target'] == 'CPU' ) 113 | checkCPU(); 114 | 115 | if( $cmdargs['target'] === null || $cmdargs['target'] == 'UPTIME' ) 116 | checkReboot(); 117 | 118 | if( $cmdargs['target'] === null || $cmdargs['target'] == 'POWER' ) 119 | checkPower(); 120 | 121 | if( $cmdargs['target'] === null || $cmdargs['target'] == 'FANS' ) 122 | checkFans(); 123 | 124 | if( $cmdargs['target'] === null || $cmdargs['target'] == 'TEMPERATURE' ) 125 | checkTemperature(); 126 | 127 | if( $cmdargs['target'] === null || $cmdargs['target'] == 'MEMORY' ) 128 | checkMemory(); 129 | 130 | if( $cmdargs['target'] === null || $cmdargs['target'] == 'DISK' ) 131 | checkDisk(); 132 | 133 | 134 | if( $status == STATUS_OK ) 135 | $msg = "OK -{$normals}\n"; 136 | else 137 | $msg = "{$criticals}{$warnings}{$unknowns}\n"; 138 | 139 | echo $msg; 140 | exit( $status ); 141 | 142 | 143 | 144 | /** 145 | * Checks the chassis temperature 146 | * 147 | */ 148 | function checkTemperature() 149 | { 150 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 151 | 152 | if( isset( $cmdargs['skip-temp'] ) && $cmdargs['skip-temp'] ) 153 | return; 154 | 155 | _log( "========== Temp check start ==========", LOG__DEBUG ); 156 | 157 | // https://mibbrowser.online/mibdb_search.php?mib=MIKROTIK-MIB 158 | 159 | $temps = [ 160 | '.1.3.6.1.4.1.14988.1.1.3.100.1.3.7101' => 'board-temperature1', 161 | '.1.3.6.1.4.1.14988.1.1.3.100.1.3.7102' => 'board-temperature2', 162 | ]; 163 | 164 | $tempdata = 'Temperatures:'; 165 | $polled = 0; 166 | 167 | foreach( $temps as $oid => $name ) { 168 | try { 169 | $temp = $snmp->get($oid); 170 | 171 | _log( "TEMP: {$name} - {$temp}C", LOG__VERBOSE ); 172 | $tempdata .= " [$name - {$temp}C]"; 173 | 174 | if( $temp > 60 ) { 175 | setStatus( STATUS_CRITICAL ); 176 | $criticals .= "{$name} is not OK, temp is {$temp}'C - check allowable max. "; 177 | } 178 | $polled++; 179 | } catch( OSS_SNMP\Exception $e ) { 180 | $tempdata .= " [$name not present?]"; 181 | } 182 | } 183 | 184 | if( !$polled ) { 185 | setStatus( STATUS_UNKNOWN ); 186 | $unknowns .= "No temperature sensors found. "; 187 | } 188 | 189 | $normals .= " $tempdata."; 190 | 191 | _log( "========== Temperature check end ==========\n", LOG__DEBUG ); 192 | } 193 | 194 | 195 | function checkFans() 196 | { 197 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 198 | 199 | if( isset( $cmdargs['skip-fans'] ) && $cmdargs['skip-fans'] ) 200 | return; 201 | 202 | _log( "========== Fans check start ==========", LOG__DEBUG ); 203 | 204 | // https://mibbrowser.online/mibdb_search.php?mib=MIKROTIK-MIB 205 | 206 | $fans = [ 207 | '.1.3.6.1.4.1.14988.1.1.3.100.1.3.7001' => 'fan1-speed', 208 | '.1.3.6.1.4.1.14988.1.1.3.100.1.3.7002' => 'fan2-speed', 209 | ]; 210 | 211 | $polled = 0; 212 | 213 | $fandata = 'Fans:'; 214 | 215 | foreach( $fans as $oid => $name ) { 216 | try { 217 | $speed = $snmp->get($oid); 218 | _log( "FAN: {$name} - {$speed} RPM", LOG__VERBOSE ); 219 | $fandata .= " [$name - {$speed} RPM]"; 220 | 221 | if( !$speed ) { 222 | setStatus( STATUS_CRITICAL ); 223 | $criticals .= "{$name} is not OK, speed is {$speed} RPM. "; 224 | } else if( $speed < 300 ) { 225 | setStatus( STATUS_CRITICAL ); 226 | $criticals .= "{$name} is not OK, speed is only {$speed} RPM. "; 227 | } 228 | 229 | $polled++; 230 | } catch( OSS_SNMP\Exception $e ) { 231 | $fandata .= " [$name not present?]"; 232 | } 233 | } 234 | 235 | if( !$polled ) { 236 | setStatus( STATUS_UNKNOWN ); 237 | $unknowns .= "No fans found. "; 238 | } 239 | 240 | 241 | $normals .= " $fandata."; 242 | 243 | 244 | _log( "========== FAN check end ==========\n", LOG__DEBUG ); 245 | 246 | } 247 | 248 | 249 | 250 | function checkPower() 251 | { 252 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 253 | 254 | if( isset( $cmdargs['skip-psu'] ) && $cmdargs['skip-psu'] ) 255 | return; 256 | 257 | _log( "========== PSU check start ==========", LOG__DEBUG ); 258 | 259 | // https://mibbrowser.online/mibdb_search.php?mib=MIKROTIK-MIB 260 | 261 | $psus = [ 262 | '.1.3.6.1.4.1.14988.1.1.3.15.0' => 'psu1-state', 263 | '.1.3.6.1.4.1.14988.1.1.3.16.0' => 'psu1-state', 264 | ]; 265 | 266 | $polled = 0; 267 | $psudata = 'PSUs:'; 268 | 269 | foreach( $psus as $oid => $name ) { 270 | try { 271 | $state = $snmp->get($oid); 272 | _log( "PSU: {$name} - " . ( $state ? 'OK' : 'NOT OK' ), LOG__VERBOSE ); 273 | $psudata .= " [$name - " . ( $state ? 'OK' : 'NOT OK' ) . "]"; 274 | 275 | if( !$state ) { 276 | setStatus( STATUS_CRITICAL ); 277 | $criticals .= "{$name} is not OK. "; 278 | } 279 | $polled++; 280 | } catch( OSS_SNMP\Exception $e ) { 281 | $psudata .= " [$name not present?]"; 282 | } 283 | } 284 | 285 | if( !$polled ) { 286 | setStatus( STATUS_UNKNOWN ); 287 | $unknowns .= "No PSUs found. "; 288 | } 289 | 290 | $normals .= " $psudata."; 291 | 292 | 293 | _log( "========== PSU check end ==========\n", LOG__DEBUG ); 294 | } 295 | 296 | 297 | 298 | function checkMemory() 299 | { 300 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 301 | 302 | if( isset( $cmdargs['skip-mem'] ) && $cmdargs['skip-mem'] ) 303 | return; 304 | 305 | _log( "========== Memory check start ==========", LOG__DEBUG ); 306 | 307 | $memAvail = $snmp->get('1.3.6.1.2.1.25.2.3.1.5.65536'); 308 | $memUsed = $snmp->get('1.3.6.1.2.1.25.2.3.1.6.65536'); 309 | 310 | $memUtil = (int)((100*$memUsed)/$memAvail); 311 | 312 | $memData = " Memory (usage%):"; 313 | 314 | if( $memUtil > $cmdargs['memcrit'] ) 315 | { 316 | setStatus( STATUS_CRITICAL ); 317 | $criticals .= "Memory usage at {$memUtil}%. "; 318 | } 319 | else if( $memUtil > $cmdargs['memwarn'] ) 320 | { 321 | setStatus( STATUS_WARNING ); 322 | $warningss .= "Memory usage at {$memUtil}%. "; 323 | } 324 | else 325 | { 326 | $memData .= " {$memUtil}%"; 327 | } 328 | 329 | $normals .= $memData . '. '; 330 | 331 | _log( "========== Memory check end ==========\n", LOG__DEBUG ); 332 | } 333 | 334 | 335 | function checkDisk() 336 | { 337 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 338 | 339 | if( isset( $cmdargs['skip-disk'] ) && $cmdargs['skip-disk'] ) 340 | return; 341 | 342 | _log( "========== Disk check start ==========", LOG__DEBUG ); 343 | 344 | $diskAvail = $snmp->get('1.3.6.1.2.1.25.2.3.1.5.131072'); 345 | $diskUsed = $snmp->get('1.3.6.1.2.1.25.2.3.1.6.131072'); 346 | 347 | $diskUtil = (int)((100*$diskUsed)/$diskAvail); 348 | 349 | $diskData = " Disk (usage%):"; 350 | 351 | if( $diskUtil > $cmdargs['diskcrit'] ) 352 | { 353 | setStatus( STATUS_CRITICAL ); 354 | $criticals .= "Dick usage at {$diskUtil}%. "; 355 | } 356 | else if( $diskUtil > $cmdargs['diskwarn'] ) 357 | { 358 | setStatus( STATUS_WARNING ); 359 | $warningss .= "Disk usage at {$memUtil}%. "; 360 | } 361 | else 362 | { 363 | $diskData .= " {$diskUtil}%"; 364 | } 365 | 366 | $normals .= $diskData . '. '; 367 | 368 | _log( "========== Disk check end ==========\n", LOG__DEBUG ); 369 | } 370 | 371 | 372 | function checkReboot() 373 | { 374 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 375 | 376 | if( isset( $cmdargs['skip-reboot'] ) && $cmdargs['skip-reboot'] ) 377 | return; 378 | 379 | _log( "========== Reboot check start ==========", LOG__DEBUG ); 380 | 381 | $bootTimeSecs = $snmp->get( '1.3.6.1.2.1.25.1.1.0' )/100; 382 | 383 | 384 | if( ( isset( $cmdargs['lastcheck'] ) && $cmdargs['lastcheck'] && $bootTimeSecs <= $cmdargs['lastcheck'] ) 385 | || ( $bootTimeSecs <= $cmdargs['reboot'] ) ) 386 | { 387 | setStatus( STATUS_CRITICAL ); 388 | $criticals .= sprintf( "Device rebooted %0.1f minutes ago. ", ( $bootTimeSecs / 60.0 ) ); 389 | } 390 | 391 | $up = $bootTimeSecs / 60.0 / 60.0; 392 | 393 | if( $up < 24 ) 394 | $up = sprintf( "Uptime: %0.1f hours. ", $up ); 395 | else 396 | $up = sprintf( "Uptime: %0.1f days. ", $up / 24 ); 397 | 398 | _log( "Last reboot: " . ( $bootTimeSecs / 60.0 ) . " minutes ago", LOG__VERBOSE ); 399 | _log( $up, LOG__VERBOSE ); 400 | 401 | $normals .= " {$up}"; 402 | 403 | _log( "========== Reboot check end ==========", LOG__DEBUG ); 404 | } 405 | 406 | 407 | 408 | function checkCPU() 409 | { 410 | global $snmp, $cmdargs, $periods, $criticals, $warnings, $unknowns, $normals; 411 | 412 | if( isset( $cmdargs['skip-cpu'] ) && $cmdargs['skip-cpu'] ) 413 | return; 414 | 415 | _log( "========== CPU check start ==========", LOG__DEBUG ); 416 | 417 | $cpus = $snmp->walk1d( '1.3.6.1.2.1.25.3.3.1.2'); 418 | 419 | list( $w, $c ) = explode( ',', $cmdargs["thres-cpu"] ); 420 | 421 | $cpudata = 'CPUS 1min load avg:'; 422 | 423 | foreach( $cpus as $cpu => $util ) { 424 | 425 | _log( "CPU: #{$cpu} - {$util}; ", LOG__VERBOSE ); 426 | $cpudata .= " [CPU #{$cpu}: {$util}%]"; 427 | 428 | if( $util >= $c ) 429 | { 430 | setStatus( STATUS_CRITICAL ); 431 | $criticals .= "CPU #{$cpu} 1min usage at {$util}%. "; 432 | } 433 | else if( $util >= $w ) 434 | { 435 | setStatus( STATUS_WARNING ); 436 | $warnings .= "CPU #{$cpu} 1min usage at {$util}%. "; 437 | } 438 | } 439 | 440 | $normals .= " $cpudata."; 441 | } 442 | 443 | 444 | 445 | /** 446 | * Parses (and checks some) command line arguments 447 | */ 448 | function parseArguments() 449 | { 450 | global $checkOptions, $cmdargs, $checksEnabled, $periods, $periodsEnabled, $argc, $argv; 451 | 452 | if( $argc == 1 ) 453 | { 454 | printUsage( true ); 455 | exit( STATUS_UNKNOWN ); 456 | } 457 | 458 | $i = 1; 459 | 460 | 461 | while( $i < $argc ) 462 | { 463 | if( $argv[$i][0] != '-' ) 464 | { 465 | $i++; 466 | continue; 467 | } 468 | 469 | switch( $argv[$i][1] ) 470 | { 471 | 472 | case 'V': 473 | printVersion(); 474 | exit( STATUS_OK ); 475 | break; 476 | 477 | case 'v': 478 | $cmdargs['log_level'] = LOG__VERBOSE; 479 | $i++; 480 | break; 481 | 482 | case 'd': 483 | $cmdargs['log_level'] = LOG__DEBUG; 484 | $i++; 485 | break; 486 | 487 | case 'c': 488 | if( !isset( $argv[$i+1] ) ) { printUsage( true ); exit( STATUS_UNKNOWN ); } 489 | $cmdargs['community'] = $argv[$i+1]; 490 | $i++; 491 | break; 492 | 493 | case 't': 494 | if( !isset( $argv[$i+1] ) ) { printUsage( true ); exit( STATUS_UNKNOWN ); } 495 | $cmdargs['target'] = $argv[$i+1]; 496 | $i++; 497 | break; 498 | 499 | case 'h': 500 | if( !isset( $argv[$i+1] ) ) { printUsage( true ); exit( STATUS_UNKNOWN ); } 501 | $cmdargs['host'] = $argv[$i+1]; 502 | $i++; 503 | break; 504 | 505 | case 'p': 506 | if( !isset( $argv[$i+1] ) ) { printUsage( true ); exit( STATUS_UNKNOWN ); } 507 | $cmdargs['port'] = $argv[$i+1]; 508 | $i++; 509 | break; 510 | 511 | case '?': 512 | printHelp(); 513 | exit( STATUS_OK ); 514 | break; 515 | 516 | default: 517 | if( !isset( $argv[$i+1] ) || substr( $argv[$i+1], 0, 1 ) == '-' ) 518 | $cmdargs[ substr( $argv[$i], 2 ) ] = true; 519 | else 520 | $cmdargs[ substr( $argv[$i], 2 ) ] = $argv[$i+1]; 521 | 522 | $i++; 523 | break; 524 | } 525 | 526 | } 527 | 528 | } 529 | 530 | 531 | /** 532 | * Sets the planned exit status without overriding a previous error states. 533 | * 534 | * @param int $new_status New status to set. 535 | * @return void 536 | */ 537 | function setStatus( $new_status ) 538 | { 539 | global $status; 540 | 541 | if( $new_status > $status ) 542 | $status = $new_status; 543 | } 544 | 545 | /** 546 | * Prints a given message to stdout (or stderr as appropriate). 547 | * 548 | * @param string $log The log message. 549 | * @param int $level The log level the user has requested. 550 | * @return void 551 | */ 552 | function _log( $log, $level ) 553 | { 554 | global $cmdargs; 555 | 556 | if( $level == LOG__ERROR ) 557 | fwrite( STDERR, "$log\n" ); 558 | else if( $level <= $cmdargs['log_level'] ) 559 | print( $log . "\n" ); 560 | } 561 | 562 | 563 | /** 564 | * Print script usage instructions to the stadout 565 | */ 566 | function printUsage() 567 | { 568 | global $argv; 569 | $progname = basename( $argv[0] ); 570 | 571 | echo << -p -h [-V] [-h] [-?] [--help] 573 | 574 | END_USAGE; 575 | 576 | } 577 | 578 | 579 | /** 580 | * Print version information 581 | */ 582 | function printVersion() 583 | { 584 | global $argv; 585 | 586 | printf( basename( $argv[0] ) . " (Nagios Plugin) %s\n", VERSION ); 587 | echo "Licensed under the New BSD License\n\n"; 588 | 589 | echo << -p -h [-V] [-?] [--help] 616 | 617 | Options: 618 | 619 | -?,--help 620 | Print detailed help screen. 621 | -V 622 | Print version information. 623 | -c 624 | SNMP Community (public) 625 | -h 626 | Device to poll 627 | -t 628 | Target - omit for all, or one of: 629 | FANS|POWER|TEMPERATURE|MEMORY|CPU|UPTIME 630 | -p 631 | SNMP port (default 161) 632 | -v 633 | Verbose output 634 | -d 635 | Debug output 636 | 637 | --skip-mem Skip memory checks 638 | --memwarn Percentage of memory usage for warning (using: {$cmdargs['memwarn']}) 639 | --memcrit Percentage of memory usage for critical (using: {$cmdargs['memcrit']}) 640 | 641 | --skip-disk Skip memory checks 642 | --diskwarn Percentage of disk usage for warning (using: {$cmdargs['diskwarn']}) 643 | --diskcrit Percentage of disk usage for critical (using: {$cmdargs['diskcrit']}) 644 | 645 | 646 | --skip-temp Skip temperature checks 647 | --tempwarn Degrees Celsius for warning (using: {$cmdargs['tempwarn']}) 648 | --tempcrit Degrees Celsius for critical (using: {$cmdargs['tempwarn']}) 649 | --skip-fans Skip fan checks 650 | 651 | --skip-psu Skip PSU(s) checks 652 | --ignore-psu-notpresent Ignore PSUs that are not installed 653 | 654 | --skip-reboot Skip reboot check 655 | --lastcheck Nagios $LASTSERVICECHECK$ macro. Used by reboot check such that if the 656 | last reboot was within the last check, then an alert is generated. Overrides 657 | --reboot to ensure reboots are caught 658 | --reboot How many seconds ago should we warn that the device has been rebooted (using: {$cmdargs['reboot']}) 659 | 660 | --skip-cpu Skip all CPU utilisation checks 661 | --thres-cpu CPU warning,critical thresholds for 5sec checks (using {$cmdargs['thres-cpu']}) 662 | 663 | 664 | END_USAGE; 665 | 666 | } 667 | -------------------------------------------------------------------------------- /check_chassis_server.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # 3 | # check_chassis_server.pl - nagios plugin 4 | # 5 | # Linux / BSD Chassis Nagios Plugin 6 | # 7 | # Copyright (c) 2011, Barry O'Donovan 8 | # All rights reserved. 9 | # 10 | # Redistribution and use in source and binary forms, with or without modification, 11 | # are permitted provided that the following conditions are met: 12 | # 13 | # * Redistributions of source code must retain the above copyright notice, this 14 | # list of conditions and the following disclaimer. 15 | # 16 | # * Redistributions in binary form must reproduce the above copyright notice, this 17 | # list of conditions and the following disclaimer in the documentation and/or 18 | # other materials provided with the distribution. 19 | # 20 | # * Neither the name of Open Solutions nor the names of its contributors may be 21 | # used to endorse or promote products derived from this software without 22 | # specific prior written permission. 23 | # 24 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 25 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 | # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 28 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 32 | # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 33 | # OF THE POSSIBILITY OF SUCH DAMAGE. 34 | # 35 | 36 | use strict; 37 | 38 | use Net::SNMP; 39 | use Getopt::Long; 40 | &Getopt::Long::config( 'auto_abbrev' ); 41 | 42 | my %ERRORS = ( 43 | 'OK' , 0, 44 | 'WARNING', 1, 45 | 'CRITICAL', 2, 46 | 'UNKNOWN', 3 47 | ); 48 | 49 | my $status; 50 | my $timeout = 20; 51 | my $state = "OK"; 52 | my $answer = ""; 53 | my $int; 54 | my $snmpkey; 55 | my $key; 56 | my $community = "public"; 57 | my $port = 161; 58 | my $snmpversion = '2c'; 59 | my $username = undef; 60 | my $authprotocol = 'sha1'; 61 | my $authpassword = undef; 62 | my $privprotocol = 'aes'; 63 | my $privpassword; 64 | 65 | my $hostname = undef; 66 | my $session; 67 | my $error; 68 | my $response = undef; 69 | 70 | my $rebootWindow = 60; 71 | 72 | my %load; 73 | my %loadthres; 74 | my $loadwarn = .8; 75 | 76 | my $memwarn = 70; 77 | my $memcrit = 90; 78 | my $swapwarn = 20; 79 | my $swapcrit = 90; 80 | 81 | my $memUsage = undef; 82 | my $swapUsage = undef; 83 | 84 | my $uptime; 85 | 86 | my %LOAD_INTERVALS = ( 87 | '1MIN', 1, 88 | '5MIN', 2, 89 | '15MIN', 3 90 | ); 91 | 92 | my $usage; 93 | my $skipreboot = 0; 94 | my $skipswap = 0; 95 | my $skipmem = 0; 96 | my $skipload = 0; 97 | my $verbose = 0; 98 | my $help = 0; 99 | 100 | $status = GetOptions( 101 | "hostname=s" => \$hostname, 102 | "community=s" => \$community, 103 | "port=i" => \$port, 104 | "skipmem" => \$skipmem, 105 | "skipswap" => \$skipswap, 106 | "skipload" => \$skipload, 107 | "skipreboot" => \$skipreboot, 108 | "verbose" => \$verbose, 109 | "memwarn=i" => \$memwarn, 110 | "help|?" => \$help, 111 | "memcrit=i" => \$memcrit, 112 | "reboot=i" => \$rebootWindow, 113 | "snmpversion=s" => \$snmpversion, 114 | "username=s" => \$username, 115 | "authprotocol=s" => \$authprotocol, 116 | "authpassword=s" => \$authpassword, 117 | "privprotocol=s" => \$privprotocol, 118 | "privpassword=s" => \$privpassword, 119 | "timeout=i" => \$timeout, 120 | ); 121 | 122 | # Just in case of problems, let's not hang Nagios 123 | $SIG{'ALRM'} = sub { 124 | print( "ERROR: No snmp response from $hostname\n" ); 125 | exit $ERRORS{"UNKNOWN"}; 126 | }; 127 | alarm( $timeout ); 128 | 129 | if( !$status || $help ) { 130 | usage(); 131 | } 132 | 133 | 134 | usage() if( !defined( $hostname ) ); 135 | 136 | my @sessionargs = ( 137 | hostname => $hostname, 138 | port => $port, 139 | version => $snmpversion, 140 | translate => 0 141 | ); 142 | 143 | if ($snmpversion eq '3') { 144 | push @sessionargs, ( 145 | username => $username, 146 | authprotocol => $authprotocol, 147 | authpassword => $authpassword, 148 | privprotocol => $privprotocol, 149 | privpassword => $privpassword, 150 | ); 151 | } else { 152 | push @sessionargs, ( 153 | community => $community, 154 | ); 155 | } 156 | 157 | ($session, $error) = Net::SNMP->session(@sessionargs); 158 | 159 | if( !defined( $session ) ) 160 | { 161 | $state = 'UNKNOWN'; 162 | $answer = $error; 163 | print( "$state: $answer" ); 164 | exit $ERRORS{$state}; 165 | } 166 | 167 | # Now Query the OS Stats 168 | 169 | if( !$skipreboot ) { 170 | checkReboot(); 171 | } 172 | 173 | if( !$skipmem ) { 174 | checkMemory(); 175 | } 176 | 177 | if( !$skipload ) { 178 | checkLoad(); 179 | } 180 | 181 | $session->close; 182 | 183 | if( $state eq 'OK' ) 184 | { 185 | print "OK - "; 186 | 187 | print "Load: $load{'1MIN'} $load{'5MIN'} $load{'15MIN'}; " if !$skipload; 188 | printf( "Mem: %0.2f%%; ", $memUsage ) if( !$skipmem ); 189 | printf( "Swap: %0.2f%%; ", $swapUsage ) if( !$skipmem && !$skipswap && defined( $swapUsage ) ); 190 | printf( "Up %0.2f days", $uptime ) if( !$skipreboot ); 191 | print( "\n" ); 192 | } 193 | else 194 | { 195 | print "$answer\n"; 196 | } 197 | 198 | exit $ERRORS{$state}; 199 | 200 | 201 | 202 | 203 | 204 | 205 | sub checkMemory 206 | { 207 | my $snmpMemTable = '1.3.6.1.4.1.2021.4'; 208 | my $snmpMemTotalSwap = '1.3.6.1.4.1.2021.4.3.0'; 209 | my $snmpMemAvailSwap = '1.3.6.1.4.1.2021.4.4.0'; 210 | my $snmpMemTotalReal = '1.3.6.1.4.1.2021.4.5.0'; 211 | my $snmpMemAvailReal = '1.3.6.1.4.1.2021.4.6.0'; 212 | my $snmpMemCached = '1.3.6.1.4.1.2021.4.15.0'; 213 | my $snmpMemSwapError = '1.3.6.1.4.1.2021.4.100'; 214 | my $snmpMemSwapErrorMsg = '1.3.6.1.4.1.2021.4.101'; 215 | 216 | my $swaptotal = undef; 217 | my $swapfree = undef; 218 | my $swapError = undef; 219 | my $swapErrorMsg = undef; 220 | 221 | my $realtotal = undef; 222 | my $realfree = undef; 223 | my $cached = undef; 224 | 225 | return if( !( $response = snmpGetTable( $snmpMemTable, 'memory' ) ) ); 226 | 227 | foreach $snmpkey ( keys %{$response} ) 228 | { 229 | $snmpkey =~ /$snmpMemTotalSwap/ && do { 230 | $swaptotal = $response->{$snmpkey}; 231 | }; 232 | 233 | $snmpkey =~ /$snmpMemAvailSwap/ && do { 234 | $swapfree = $response->{$snmpkey}; 235 | }; 236 | 237 | $snmpkey =~ /$snmpMemTotalReal/ && do { 238 | $realtotal = $response->{$snmpkey}; 239 | }; 240 | 241 | $snmpkey =~ /$snmpMemAvailReal/ && do { 242 | $realfree = $response->{$snmpkey}; 243 | }; 244 | 245 | $snmpkey =~ /$snmpMemCached/ && do { 246 | $cached = $response->{$snmpkey}; 247 | }; 248 | 249 | $snmpkey =~ /$snmpMemSwapError/ && do { 250 | $swapError = $response->{$snmpkey}; 251 | }; 252 | 253 | $snmpkey =~ /$snmpMemSwapErrorMsg/ && do { 254 | $swapErrorMsg = $response->{$snmpkey}; 255 | }; 256 | } 257 | 258 | if( !defined( $cached ) ) 259 | { 260 | $cached = 0; 261 | } 262 | 263 | $memUsage = ( ( ( $realtotal - $realfree - $cached ) ) * 100 ) / $realtotal; 264 | printf( "Memory - total: $realtotal realfree: $realfree cache: $cached - Usage: %0.2f%%\n", $memUsage ) if $verbose; 265 | 266 | if( $memUsage >= $memcrit ) { 267 | &setstate( 'CRITICAL', "Memory Usage " . int( $memUsage ) . "%" ); 268 | } elsif( $memUsage >= $memwarn ) { 269 | &setstate( 'WARNING', "Memory Usage " . int( $memUsage ) . "%" ); 270 | } 271 | 272 | if( !$skipswap && defined( $swapError ) && $swapError ) { 273 | &setstate( 'CRITICAL', "Swap Error: " . $swapErrorMsg ); 274 | } 275 | 276 | if( !$skipswap && defined( $swaptotal ) && $swaptotal ) 277 | { 278 | $swapUsage = ( ( $swaptotal - $swapfree ) * 100 ) / $swaptotal; 279 | 280 | printf( "Swap - total: $swaptotal swapfree: $swapfree - Usage: %0.2f%%\n", $swapUsage ) if $verbose; 281 | 282 | if( $swapUsage >= $swapcrit ) { 283 | &setstate( 'CRITICAL', "Swap Usage " . int( $swapUsage ) . "%" ); 284 | } elsif( $swapUsage >= $swapwarn ) { 285 | &setstate( 'WARNING', "Swap Usage " . int( $swapUsage ) . "%" ); 286 | } 287 | } 288 | } 289 | 290 | sub checkReboot 291 | { 292 | my $snmpSysUpTime = '.1.3.6.1.2.1.1.3.0'; 293 | my $sysuptime; 294 | 295 | return if( !( $response = snmpGetRequest( $snmpSysUpTime, 'system uptime' ) ) ); 296 | 297 | # uptime in minutes 298 | $sysuptime = $response->{$snmpSysUpTime} / 100.0 / 60.0; 299 | 300 | if( $sysuptime <= $rebootWindow ) { 301 | &setstate( 'WARNING', sprintf( "Device rebooted %0.1f minutes ago", $sysuptime ) ); 302 | } 303 | 304 | $uptime = $sysuptime / 60.0 / 24.0; 305 | } 306 | 307 | sub checkLoad 308 | { 309 | my $snmpLoadTable = '1.3.6.1.4.1.2021.10.1'; 310 | my $snmpLoadValues = '1.3.6.1.4.1.2021.10.1.3.'; 311 | my $snmpLoadThres = '1.3.6.1.4.1.2021.10.1.4.'; 312 | 313 | return if( !( $response = snmpGetTable( $snmpLoadTable, 'system load' ) ) ); 314 | 315 | foreach $int ( keys %LOAD_INTERVALS ) 316 | { 317 | $load{$int} = $response->{$snmpLoadValues . $LOAD_INTERVALS{$int}}; 318 | $loadthres{$int} = $response->{$snmpLoadThres . $LOAD_INTERVALS{$int}}; 319 | printf( $int . ":\t" . $load{$int} . "/" . $loadthres{$int} . "\n" ) if $verbose; 320 | 321 | if( $load{$int} >= $loadthres{$int} ) { 322 | &setstate( 'CRITICAL', $int . " load average is $load{$int}" ); 323 | } elsif( $load{$int} >= ( $loadthres{$int} * $loadwarn ) ) { 324 | &setstate( 'WARNING', $int . " load average is $load{$int}" ); 325 | } 326 | } 327 | } 328 | 329 | sub usage { 330 | printf "\nUsage:\n"; 331 | printf "\n"; 332 | printf "Perl server chassis plugin for Nagios\n\n"; 333 | printf "check_chassis_server.pl -c -p \n\n"; 334 | printf "Checks:\n"; 335 | printf " * memory and swap space usage\n"; 336 | printf " * system load\n"; 337 | printf " * if the device was recently rebooted\n\n"; 338 | printf "Additional options:\n\n"; 339 | printf " --help This help message\n\n"; 340 | printf " --hostname The hostname to check\n"; 341 | printf " --community The SNMP access community\n"; 342 | printf " --skipload Skip server load checks\n"; 343 | printf " --skipmem Skip memory checks\n"; 344 | printf " --skipswap Skip swap but not real memory checks\n"; 345 | printf " --skipreboot Skip reboot check\n"; 346 | printf " --reboot How many minutes ago should we warn that the device has been rebooted (default: " . $rebootWindow . ")\n"; 347 | printf " --memwarn Percentage of memory usage for warning (default: " . $memwarn . ")\n"; 348 | printf " --memcrit Percentage of memory usage for critical (default: " . $memcrit . ")\n"; 349 | printf " --swapwarn Percentage of swap usage for warning (default: " . $swapwarn . ")\n"; 350 | printf " --swapcrit Percentage of swap usage for critical (default: " . $swapcrit . ")\n"; 351 | printf " --loadwarn Multiplier of load critical value for warning (default: " . $loadwarn . ")\n"; 352 | printf " (critical load value is taken from SNMP)\n"; 353 | printf "\nCopyright (c) 2011, Barry O'Donovan \n"; 354 | printf "All rights reserved.\n\n"; 355 | printf "This script comes with ABSOLUTELY NO WARRANTY\n"; 356 | printf "This programm is licensed under the terms of the "; 357 | printf "BSD New License (check source code for details)\n"; 358 | printf "\n\n"; 359 | 360 | exit $ERRORS{"UNKNOWN"} if !$help; 361 | exit 0; 362 | } 363 | 364 | sub setstate { 365 | my $newstate = shift( @_ ); 366 | my $message = shift( @_ ); 367 | 368 | if( $ERRORS{$newstate} > $ERRORS{$state} ) 369 | { 370 | $state = $newstate; 371 | } 372 | elsif( $newstate eq 'UNKNOWN' && $state eq 'OK' ) 373 | { 374 | $state = $newstate; 375 | } 376 | 377 | if( $answer ) { $answer .= "
\n"; } 378 | 379 | $answer .= $message; 380 | } 381 | 382 | sub snmpGetTable { 383 | my $oid = shift( @_ ); 384 | my $check = shift( @_ ); 385 | 386 | if( !defined( $response = $session->get_table( $oid ) ) ) 387 | { 388 | if( $session->error_status() == 2 || $session->error() =~ m/requested table is empty or does not exist/i ) 389 | { 390 | print "OID not supported for $check ($oid).\n" if $verbose; 391 | return 0; 392 | } 393 | 394 | $answer = $session->error(); 395 | $session->close; 396 | 397 | $state = 'CRITICAL'; 398 | print( "$state: $answer (in check for $check with OID: $oid)\n" ); 399 | exit $ERRORS{$state}; 400 | } 401 | 402 | return $response; 403 | } 404 | 405 | sub snmpGetRequest { 406 | my $oid = shift( @_ ); 407 | my $check = shift( @_ ); 408 | 409 | if( !defined( $response = $session->get_request( $oid ) ) ) 410 | { 411 | if( $session->error_status() == 2 || $session->error() =~ m/requested table is empty or does not exist/i ) 412 | { 413 | print "OID not supported for $check ($oid).\n" if $verbose; 414 | return 0; 415 | } 416 | 417 | $answer = $session->error(); 418 | $session->close; 419 | 420 | $state = 'CRITICAL'; 421 | print( "$state: $answer (in check for $check with OID: $oid)\n" ); 422 | exit $ERRORS{$state}; 423 | } 424 | 425 | return $response; 426 | } 427 | -------------------------------------------------------------------------------- /check_disk_snmp.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # 3 | # check_disk_snmp.pl - nagios plugin 4 | # 5 | # nagios: -epn 6 | # 7 | # Linux / BSD Disk Space Nagios Plugin 8 | # 9 | # Copyright (c) 2011, Barry O'Donovan 10 | # All rights reserved. 11 | # 12 | # Redistribution and use in source and binary forms, with or without modification, 13 | # are permitted provided that the following conditions are met: 14 | # 15 | # * Redistributions of source code must retain the above copyright notice, this 16 | # list of conditions and the following disclaimer. 17 | # 18 | # * Redistributions in binary form must reproduce the above copyright notice, this 19 | # list of conditions and the following disclaimer in the documentation and/or 20 | # other materials provided with the distribution. 21 | # 22 | # * Neither the name of Open Solutions nor the names of its contributors may be 23 | # used to endorse or promote products derived from this software without 24 | # specific prior written permission. 25 | # 26 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 27 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 28 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 | # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 30 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 31 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 33 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 34 | # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 35 | # OF THE POSSIBILITY OF SUCH DAMAGE. 36 | # 37 | 38 | use strict; 39 | 40 | use Net::SNMP; 41 | use Getopt::Long; 42 | &Getopt::Long::config( 'auto_abbrev' ); 43 | use Pod::Usage; 44 | 45 | my %ERRORS = ( 46 | 'UNSET', -1, 47 | 'OK' , 0, 48 | 'WARNING', 1, 49 | 'CRITICAL', 2, 50 | 'UNKNOWN', 3 51 | ); 52 | 53 | my $status; 54 | my $timeout = 20; 55 | my $state = "UNSET"; 56 | my $answer = ""; 57 | my $int; 58 | my $snmpkey; 59 | my $key; 60 | my $community = "public"; 61 | my $port = 161; 62 | my $snmpversion = '2c'; 63 | my $username = undef; 64 | my $authprotocol = 'sha1'; 65 | my $authpassword = undef; 66 | my $privprotocol = 'aes'; 67 | my $privpassword; 68 | 69 | my $hostname = undef; 70 | my $session; 71 | my $error; 72 | my $response = undef; 73 | 74 | my $diskstats = ''; 75 | 76 | my $usage; 77 | my $verbose = 0; 78 | my $help = 0; 79 | my $manpage = 0; 80 | my $devicesonly = 0; 81 | 82 | my $warning = 10; 83 | my $nowarningrecalc = 0; 84 | 85 | my $calcmethod = 1; 86 | 87 | $status = GetOptions( 88 | "hostname=s" => \$hostname, 89 | "community=s" => \$community, 90 | "port=i" => \$port, 91 | "verbose" => \$verbose, 92 | "warning=i" => \$warning, 93 | "no-warning-recalc" => \$nowarningrecalc, 94 | "devices-only" => \$devicesonly, 95 | "calc-method=i" => \$calcmethod, 96 | "help|?" => \$help, 97 | "man" => \$manpage, 98 | "snmpversion=s" => \$snmpversion, 99 | "username=s" => \$username, 100 | "authprotocol=s" => \$authprotocol, 101 | "authpassword=s" => \$authpassword, 102 | "privprotocol=s" => \$privprotocol, 103 | "privpassword=s" => \$privpassword, 104 | "timeout=i" => \$timeout, 105 | ); 106 | 107 | # Just in case of problems, let's not hang Nagios 108 | $SIG{'ALRM'} = sub { 109 | print( "ERROR: No snmp response from $hostname\n" ); 110 | exit $ERRORS{"UNKNOWN"}; 111 | }; 112 | alarm( $timeout ); 113 | 114 | pod2usage(-verbose => 2) if $manpage; 115 | 116 | pod2usage( -verbose => 1 ) if $help; 117 | 118 | pod2usage() if !$status || !$hostname; 119 | 120 | my @sessionargs = ( 121 | hostname => $hostname, 122 | port => $port, 123 | version => $snmpversion, 124 | translate => 0 125 | ); 126 | 127 | if ($snmpversion eq '3') { 128 | push @sessionargs, ( 129 | username => $username, 130 | authprotocol => $authprotocol, 131 | authpassword => $authpassword, 132 | privprotocol => $privprotocol, 133 | privpassword => $privpassword, 134 | ); 135 | } else { 136 | push @sessionargs, ( 137 | community => $community, 138 | ); 139 | } 140 | 141 | ($session, $error) = Net::SNMP->session(@sessionargs); 142 | 143 | if( !defined( $session ) ) 144 | { 145 | $state = 'UNKNOWN'; 146 | $answer = $error; 147 | print( "$state: $answer" ); 148 | exit $ERRORS{$state}; 149 | } 150 | 151 | checkDiskSpace(); 152 | 153 | $session->close; 154 | 155 | if( $state eq 'OK' ) { 156 | print "OK - $diskstats\n"; 157 | } 158 | else { 159 | print "$answer\n"; 160 | } 161 | 162 | exit $ERRORS{$state}; 163 | 164 | 165 | 166 | 167 | 168 | 169 | sub checkDiskSpace 170 | { 171 | my $snmpDiskTable = '1.3.6.1.4.1.2021.9.1'; 172 | 173 | my $snmpPath = $snmpDiskTable . '.2'; 174 | my $snmpDevice = $snmpDiskTable . '.3'; 175 | my $snmpMinPercent = $snmpDiskTable . '.5'; 176 | my $snmpTotal = $snmpDiskTable . '.6'; 177 | my $snmpAvail = $snmpDiskTable . '.7'; 178 | my $snmpUsed = $snmpDiskTable . '.8'; 179 | my $snmpPercentUsed = $snmpDiskTable . '.9'; 180 | my $snmpPercentINode = $snmpDiskTable . '.10'; 181 | 182 | return if( !( $response = snmpGetTable( $snmpDiskTable, 'disk table' ) ) ); 183 | 184 | $state = 'OK'; 185 | 186 | foreach $snmpkey ( keys %{$response} ) 187 | { 188 | # check each disk (by iterating the paths) 189 | $snmpkey =~ /$snmpPath/ && do { 190 | 191 | if( $snmpkey =~ /$snmpPath\.(\d+)$/ ) 192 | { 193 | my $t_index = $1; 194 | 195 | my $t_path = $response->{$snmpPath . '.' . $t_index}; 196 | my $t_device = $response->{$snmpDevice . '.' . $t_index}; 197 | my $t_minpercent = $response->{$snmpMinPercent . '.' . $t_index}; 198 | my $t_total = $response->{$snmpTotal . '.' . $t_index}; 199 | my $t_avail = $response->{$snmpAvail . '.' . $t_index}; 200 | my $t_used = $response->{$snmpUsed . '.' . $t_index}; 201 | my $t_percentused = $response->{$snmpPercentUsed . '.' . $t_index}; 202 | my $t_percentinode = $response->{$snmpPercentINode . '.' . $t_index}; 203 | 204 | 205 | if( !defined( $t_minpercent ) ) { 206 | $t_minpercent = 0; 207 | } 208 | 209 | if( $devicesonly && $t_device !~ m/^\/dev\// ) { 210 | next; 211 | } 212 | 213 | if( $calcmethod == 2 ) { 214 | $t_percentused = ( $t_total - $t_avail ) / ( $t_total / 100.0 ); 215 | } 216 | 217 | if( !defined( $t_percentinode ) ) { 218 | $t_percentinode = 'UNKNOWN'; 219 | } 220 | 221 | print( "Disk: $t_path ($t_device) $t_used/$t_total ($t_percentused\%) used with $t_avail available [min: $t_minpercent]" 222 | . ". inode usage: $t_percentinode%%\n" ) if $verbose; 223 | 224 | my $t_warning = $warning; 225 | if( $t_minpercent < 10 && !$nowarningrecalc ) { 226 | $t_warning = $t_minpercent * 2; 227 | } 228 | 229 | $diskstats .= sprintf( "%s (%s) %d%% (inodes: %d%%); ", $t_path, $t_device, $t_percentused, $t_percentinode ); 230 | 231 | if( $t_percentused >= ( 100 - $t_minpercent ) ) { 232 | &setstate( 'CRITICAL', "Disk usage for $t_path ($t_device) is $t_percentused\%" ); 233 | } elsif( $t_percentused >= ( 100 - $t_minpercent - $t_warning ) ) { 234 | &setstate( 'WARNING', "Disk usage for $t_path ($t_device) is $t_percentused\%" ); 235 | } 236 | 237 | if( $t_percentinode ne 'UNKNOWN' ) { 238 | if( $t_percentinode >= ( 100 - $t_minpercent ) ) { 239 | &setstate( 'CRITICAL', "Disk inode usage for $t_path ($t_device) is $t_percentinode\%" ); 240 | } elsif( $t_percentinode >= ( 100 - $t_minpercent - $t_warning ) ) { 241 | &setstate( 'WARNING', "Disk inode usage for $t_path ($t_device) is $t_percentinode\%" ); 242 | } 243 | } 244 | } 245 | } 246 | } 247 | } 248 | 249 | 250 | 251 | sub setstate { 252 | my $newstate = shift( @_ ); 253 | my $message = shift( @_ ); 254 | 255 | if( $ERRORS{$newstate} > $ERRORS{$state} ) 256 | { 257 | $state = $newstate; 258 | } 259 | elsif( $newstate eq 'UNKNOWN' && $state eq 'OK' ) 260 | { 261 | $state = $newstate; 262 | } 263 | 264 | if( $answer ) { $answer .= "
\n"; } 265 | 266 | $answer .= $message; 267 | } 268 | 269 | sub snmpGetTable { 270 | my $oid = shift( @_ ); 271 | my $check = shift( @_ ); 272 | 273 | if( !defined( $response = $session->get_table( $oid ) ) ) 274 | { 275 | if( $session->error_status() == 2 || $session->error() =~ m/requested table is empty or does not exist/i ) 276 | { 277 | print "OID not supported for $check ($oid).\n" if $verbose; 278 | return 0; 279 | } 280 | 281 | $answer = $session->error(); 282 | $session->close; 283 | 284 | $state = 'CRITICAL'; 285 | print( "$state: $answer (in check for $check with OID: $oid)\n" ); 286 | exit $ERRORS{$state}; 287 | } 288 | 289 | return $response; 290 | } 291 | 292 | 293 | __END__ 294 | 295 | =head1 check_disk_snmp.pl 296 | 297 | check_disk_snmp.pl - Nagios plugin to check disks on a server for usage 298 | 299 | =head1 SYNOPSIS 300 | 301 | check_disk_snmp.pl --hostname [options] 302 | 303 | Options: 304 | --hostname the hostname or IP of the server to check 305 | --port the port to query for SNMP 306 | --community the SNMP community to use 307 | --verbose display additional information 308 | --help extended help message 309 | --man full manual page 310 | --warning the percent offset from critical which will generate a warning 311 | --no-warning-recalc don't automatically recalculate the warning offset (see --man) 312 | --devices-only only check disks with devices in /dev/ on the server 313 | --calc-method calculation method to use (default 1) 314 | --snmpversion specify the SNMP version (2c or 3) 315 | --username specify the SNMPv3 username 316 | --authprotocol specify the SNMPv3 authentication protocol 317 | --authpassword specify the SNMPv3 authentication username 318 | --privprotocol specify the SNMPv3 privacy protocol 319 | --privpassword specify the SNMPv3 privacy username 320 | 321 | =head1 OPTIONS AND ARGUMENTS 322 | 323 | =over 8 324 | 325 | =item B<--verbose> 326 | 327 | Print additional information including all disks found and their usage states. 328 | 329 | =item B<--help> 330 | 331 | Expanded help message. 332 | 333 | =item B<--man> 334 | 335 | Full manual page. 336 | 337 | =item B<--warning> 338 | 339 | The thresholds for critical alerts are taken from SNMP. This parameter sets the warning 340 | threshold by reducing the required percentage by this value. 341 | 342 | =item B<--no-warning-recalc> 343 | 344 | The threshold for warning is recalculated for small values of the critical threshold. This stops that 345 | behavior. See --man for more details. 346 | 347 | =item B<--devices-only> 348 | 349 | Useful to ignore kernel and other virtual filesystems such as /proc, /sys, etc 350 | 351 | =item B<--calc-method> 352 | 353 | The calculation method to use when calculating free space. See --man for more information. 354 | 355 | 356 | =back 357 | 358 | =head1 DESCRIPTION 359 | 360 | B will read all disk entries via SNMP on the given host 361 | and issue a warning or critical alert if given thresholds are exceeded. 362 | 363 | =head2 CONFIGURING YOUR SNMP DAEMON 364 | 365 | This script requires that you have configured your SNMP daemon to provide disk 366 | usage information. The typical snmpd.conf configuration would be: 367 | 368 | disk PATH MINPERCENT% 369 | includeAllDisks MINPERCENT% 370 | 371 | You do not need any C lines if you have C but you can use both such that 372 | the individual C lines can override the C defaults. 373 | 374 | This script takes the C value B - 375 | namely, the critical threshold is C<100% - MINPERCENT%> and the warning threshold is 376 | C<100% - MINPERCENT% - WARNING_OFFSET> where C is set via C<--warning> and 377 | defaults to 10%. For example, if you had: 378 | 379 | disk / 10% 380 | disk /var 15% 381 | 382 | then for the root partition, a warning alert would be generated when usage reaches 80% and a critical 383 | alert when usage reaches 90%. For C then it would be 75% and 85% respectivily. 384 | 385 | =head2 AUTORECALULATION OF WARNING 386 | 387 | If the C for a disk is less that 10, then C<--warning> is automatically recalculated for 388 | that disk to C. To stop this behavior, use C<--no-warning-recalc>. 389 | 390 | =head2 CALCULATION METHOD 391 | 392 | In practice some systems return unusual / unexpected values in the SNMP table. To get around this, 393 | we have defined multiple calculation methods: 394 | 395 | =over 8 396 | 397 | =item B<1> 398 | 399 | The default. Just takes the used percentage directly from the SNMP table. 400 | 401 | =item B<2> 402 | 403 | Calcutes the percentage used from the total and available data in the SNMP table 404 | ignoring the used data. I.e. 405 | 406 | C<$t_total - $t_avail ) / ( $t_total / 100.0 )>. 407 | 408 | =back 409 | 410 | =head1 AUTHOR 411 | 412 | Written by Barry O'Donovan as part of the work we 413 | do in Open Solutions (http://www.opensolutions.ie/). 414 | 415 | =head1 COPYRIGHT 416 | 417 | Copyright (c) 2011, Barry O'Donovan . 418 | All rights reserved. 419 | 420 | Released under the terms of the modified BSD license. 421 | See http://opensource.org/licenses/alphabetical for full text. 422 | 423 | =head1 SEE ALSO 424 | 425 | https://github.com/barryo/nagios-plugins 426 | 427 | =cut 428 | -------------------------------------------------------------------------------- /check_pop3_login.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | #use strict; 4 | use Net::POP3; 5 | 6 | if ($#ARGV != 2) 7 | { 8 | print "Error in usage: hostname, username & password required"; 9 | exit 3; 10 | } 11 | 12 | my $hostname = $ARGV[0]; 13 | my $username = $ARGV[1]; 14 | my $password = $ARGV[2]; 15 | 16 | my $pop = Net::POP3->new($hostname, Timeout => 60); 17 | my $msgnum = $pop->login($username, $password); 18 | my $retval = 2; 19 | 20 | if ( !defined($msgnum) ) 21 | { 22 | print "Critical: unable to log on\r\n"; 23 | $retval = 2; 24 | } else 25 | { 26 | $retval = 0; 27 | print "OK: successfully logged in.\r\n"; 28 | } 29 | 30 | $pop->quit; 31 | exit $retval; 32 | 33 | -------------------------------------------------------------------------------- /check_port_errors.php: -------------------------------------------------------------------------------- 1 | #! /usr/bin/php 2 | 51 | * @author The Skilled Team of PHP Developers at Open Solutions 52 | */ 53 | 54 | date_default_timezone_set('Europe/Dublin'); 55 | define( "VERSION", '1.0.0' ); 56 | 57 | ini_set( 'max_execution_time', '55' ); 58 | 59 | ini_set( 'display_errors', true ); 60 | ini_set( 'display_startup_errors', true ); 61 | 62 | define( "STATUS_OK", 0 ); 63 | define( "STATUS_WARNING", 1 ); 64 | define( "STATUS_CRITICAL", 2 ); 65 | define( "STATUS_UNKNOWN", 3 ); 66 | 67 | define( "LOG__NONE", 0 ); 68 | define( "LOG__ERROR", 1 ); 69 | define( "LOG__VERBOSE", 2 ); 70 | define( "LOG__DEBUG", 3 ); 71 | 72 | // initialise some variables 73 | $status = STATUS_OK; 74 | $log_level = LOG__NONE; 75 | 76 | 77 | // possible output strings 78 | $criticals = ""; 79 | $warnings = ""; 80 | $unknowns = ""; 81 | $normals = ""; 82 | 83 | // set default values for command line arguments 84 | $cmdargs = [ 85 | 'port' => '161', 86 | 'log_level' => LOG__NONE 87 | ]; 88 | 89 | // port interfaces to ignore. 90 | // 91 | // The array key is the hostname. The value is the shortened snmp name. 92 | 93 | $ignoreports = [ 94 | // 'core-router02.example.com' => 'Gi0/19', 95 | ]; 96 | 97 | // parse the command line arguments 98 | parseArguments(); 99 | 100 | 101 | // create a memcache key: 102 | $MCKEY = 'NAGIOS_CHECK_PORT_ERRORS_' . md5( $cmdargs['host'] ); 103 | 104 | if( !class_exists( 'Memcache' ) ) 105 | die( "ERROR: php-memcache is required\n" ); 106 | 107 | $mc = new Memcache; 108 | $mc->connect( 'localhost', 11211 ) or die( "ERROR: Could not connect to memcache on localhost:11211\n" ); 109 | 110 | _log( "Connected to Memcache with version: " . $mc->getVersion(), LOG__DEBUG ); 111 | 112 | 113 | require 'OSS_SNMP/OSS_SNMP/SNMP.php'; 114 | 115 | $snmp = new \OSS_SNMP\SNMP( 116 | $cmdargs['host'], 117 | $cmdargs['community'], 118 | $cmdargs['snmpversion'], 119 | $cmdargs['seclevel'], 120 | $cmdargs['authprotocol'], 121 | $cmdargs['authpassword'], 122 | $cmdargs['privprotocol'], 123 | $cmdargs['privpassword'], 124 | ); 125 | 126 | $snmp->setSecName($cmdargs['username']); 127 | 128 | // get interface types for later filtering 129 | $types = $snmp->useIface()->types(); 130 | $names = filterForType( $snmp->useIface()->names(), $types, OSS_SNMP\MIBS\Iface::IF_TYPE_ETHERNETCSMACD ); 131 | 132 | _log( "Found " . count( $names ) . " physical ethernet ports", LOG__DEBUG ); 133 | 134 | 135 | // get current error counters 136 | $ifInErrors = filterForType( $snmp->useIface()->inErrors(), $types, OSS_SNMP\MIBS\Iface::IF_TYPE_ETHERNETCSMACD ); 137 | $ifOutErrors = filterForType( $snmp->useIface()->outErrors(), $types, OSS_SNMP\MIBS\Iface::IF_TYPE_ETHERNETCSMACD ); 138 | 139 | _log( "Found " . count( $ifInErrors ) . " entries for in errors on physical ethernet ports", LOG__DEBUG ); 140 | _log( "Found " . count( $ifOutErrors ) . " entries for out errors on physical ethernet ports", LOG__DEBUG ); 141 | 142 | // delete unwanted entries 143 | foreach ( array_keys( $ignoreports ) as $hostkey) { 144 | 145 | if ($cmdargs[ 'host' ] == $hostkey) { 146 | $portid = array_keys( $names, $ignoreports[ $hostkey ] )[0]; 147 | 148 | if( isset ($portid) ) { 149 | unset( $ifInErrors[ $portid ] ); 150 | unset( $ifOutErrors[ $portid ] ); 151 | } 152 | 153 | } 154 | 155 | } 156 | 157 | 158 | // if we don't have any entries already, set them and send an unknown 159 | $cache = $mc->get( $MCKEY ); 160 | 161 | // save the new values to memcache 162 | $newcache = [ 163 | 'ifInErrors' => $ifInErrors, 164 | 'ifOutErrors' => $ifOutErrors, 165 | 'timestamp' => time() 166 | ]; 167 | 168 | if( !$mc->set( $MCKEY, $newcache, 0, 900 ) ) { 169 | echo "UNKNOWN - could not update cache\n"; 170 | exit( STATUS_UNKNOWN ); 171 | } 172 | 173 | if( $cache === false ) { 174 | echo "UNKNOWN - no previous cached entries found\n"; 175 | exit( STATUS_UNKNOWN ); 176 | } 177 | 178 | $msg = ''; 179 | 180 | foreach( [ 'IN' => 'ifInErrors', 'OUT' => 'ifOutErrors' ] as $dir => $name ) 181 | { 182 | $result = subtractArray( $$name, $cache[ $name ] ); 183 | 184 | if( count( $result ) ) { 185 | setStatus( STATUS_CRITICAL ); 186 | 187 | if( $criticals == '' ) 188 | $criticals = 'CRITICAL: In the last ' . ( time() - $cache['timestamp'] ) . ' seconds, port errors were found.'; 189 | 190 | $criticals .= " [DIRECTION: {$dir}] =>"; 191 | 192 | foreach( $result as $k => $v ) 193 | $criticals .= " " . $names[ $k ] . ": {$v} errors;"; 194 | 195 | $criticals .= ' ***'; 196 | } 197 | else 198 | $normals .= " No errors found for $dir packets on all interfaces."; 199 | } 200 | 201 | 202 | if( $status == STATUS_OK ) 203 | $msg = "OK -{$normals}\n"; 204 | else 205 | $msg .= "{$criticals}{$warnings}{$unknowns}{$normals}\n"; 206 | 207 | echo $msg; 208 | exit( $status ); 209 | 210 | 211 | function subtractArray( $new, $old ) 212 | { 213 | $result = []; 214 | foreach( $new as $k => $v ) 215 | if( $v - $old[$k] > 0 ) 216 | $result[$k] = $v - $old[$k]; 217 | 218 | return $result; 219 | } 220 | 221 | 222 | 223 | function filterForType( $ports, $types, $type ) 224 | { 225 | foreach( $ports as $k => $v ) 226 | if( $types[$k] !== $type ) 227 | unset( $ports[ $k ] ); 228 | 229 | return $ports; 230 | } 231 | 232 | 233 | 234 | /** 235 | * Parses (and checks some) command line arguments 236 | */ 237 | function parseArguments() 238 | { 239 | global $checkOptions, $cmdargs, $argc, $argv; 240 | 241 | if( $argc == 1 ) 242 | { 243 | printUsage( true ); 244 | exit( STATUS_UNKNOWN ); 245 | } 246 | 247 | $i = 1; 248 | 249 | $cmdargs['community'] = ''; 250 | $cmdargs['snmpversion'] = '2c'; 251 | $cmdargs['authprotocol'] = 'SHA'; 252 | $cmdargs['privprotocol'] = 'AES'; 253 | $cmdargs['seclevel'] = 'authPriv'; 254 | 255 | while( $i < $argc ) 256 | { 257 | if( $argv[$i][0] != '-' ) 258 | { 259 | $i++; 260 | continue; 261 | } 262 | 263 | switch( $argv[$i][1] ) 264 | { 265 | 266 | case 'V': 267 | printVersion(); 268 | exit( STATUS_OK ); 269 | break; 270 | 271 | case 'v': 272 | $cmdargs['log_level'] = LOG__VERBOSE; 273 | $i++; 274 | break; 275 | 276 | case 'd': 277 | $cmdargs['log_level'] = LOG__DEBUG; 278 | $i++; 279 | break; 280 | 281 | case 'c': 282 | $cmdargs['community'] = $argv[$i+1]; 283 | $i++; 284 | break; 285 | 286 | case 'h': 287 | $cmdargs['host'] = $argv[$i+1]; 288 | $i++; 289 | break; 290 | 291 | case 'p': 292 | $cmdargs['port'] = $argv[$i+1]; 293 | $i++; 294 | break; 295 | 296 | case 's': 297 | $cmdargs['snmpversion'] = $argv[$i+1]; 298 | $i++; 299 | break; 300 | 301 | case 'u': 302 | $cmdargs['username'] = $argv[$i+1]; 303 | $i++; 304 | break; 305 | 306 | case 'a': 307 | $cmdargs['authprotocol'] = $argv[$i+1]; 308 | $i++; 309 | break; 310 | 311 | case 'A': 312 | $cmdargs['authpassword'] = $argv[$i+1]; 313 | $i++; 314 | break; 315 | 316 | case 'e': 317 | $cmdargs['privprotocol'] = $argv[$i+1]; 318 | $i++; 319 | break; 320 | 321 | case 'E': 322 | $cmdargs['privpassword'] = $argv[$i+1]; 323 | $i++; 324 | break; 325 | 326 | case 'l': 327 | $cmdargs['seclevel'] = $argv[$i+1]; 328 | $i++; 329 | break; 330 | 331 | case '?': 332 | printHelp(); 333 | exit( STATUS_OK ); 334 | break; 335 | 336 | default: 337 | if( !isset( $argv[$i+1] ) || substr( $argv[$i+1], 0, 1 ) == '-' ) 338 | $cmdargs[ substr( $argv[$i], 2 ) ] = true; 339 | else 340 | $cmdargs[ substr( $argv[$i], 2 ) ] = $argv[$i+1]; 341 | 342 | $i++; 343 | break; 344 | } 345 | 346 | } 347 | 348 | } 349 | 350 | 351 | /** 352 | * Sets the planned exit status without overriding a previous error states. 353 | * 354 | * @param int $new_status New status to set. 355 | * @return void 356 | */ 357 | function setStatus( $new_status ) 358 | { 359 | global $status; 360 | 361 | if( $new_status > $status ) 362 | $status = $new_status; 363 | } 364 | 365 | /** 366 | * Prints a given message to stdout (or stderr as appropriate). 367 | * 368 | * @param string $log The log message. 369 | * @param int $level The log level the user has requested. 370 | * @return void 371 | */ 372 | function _log( $log, $level ) 373 | { 374 | global $cmdargs; 375 | 376 | if( $level == LOG__ERROR ) 377 | fwrite( STDERR, "$log\n" ); 378 | else if( $level <= $cmdargs['log_level'] ) 379 | print( $log . "\n" ); 380 | } 381 | 382 | 383 | /** 384 | * Print script usage instructions to the stadout 385 | */ 386 | function printUsage() 387 | { 388 | global $argv; 389 | $progname = basename( $argv[0] ); 390 | 391 | echo << | -s 3] -p -h [-V] [-h] [-?] [--help] 393 | 394 | END_USAGE; 395 | 396 | } 397 | 398 | 399 | /** 400 | * Print version information 401 | */ 402 | function printVersion() 403 | { 404 | global $argv; 405 | 406 | printf( basename( $argv[0] ) . " (Nagios Plugin) %s\n", VERSION ); 407 | echo "Licensed under the New BSD License\n\n"; 408 | 409 | echo << | -s 3] -p -h [-V] [-?] [--help] 436 | 437 | WARNING: SCRIPT IS HARD CODED TO CONNECT TO A MEMCACHE INSTANCE ON: 438 | localhost:11211 439 | 440 | Options: 441 | 442 | -?,--help 443 | Print detailed help screen. 444 | -V 445 | Print version information. 446 | -c 447 | SNMP Community (public) 448 | -h 449 | Device to poll 450 | -p 451 | SNMP port (default 161) 452 | -v 453 | Verbose output 454 | -d 455 | Debug output 456 | -s 457 | SNMP Version (2c or 3) 458 | -u 459 | SNMPv3 username 460 | -a 461 | SNMPv3 authentication protocol 462 | -A 463 | SNMPv3 authentication password 464 | -e 465 | SNMPv3 encryption / privacy protocol 466 | -E 467 | SNMPv3 encryption / privacy password 468 | -l 469 | SNMPv3 security level (noAuthNoPriv|authNoPriv|authPriv) 470 | 471 | END_USAGE; 472 | 473 | } 474 | -------------------------------------------------------------------------------- /check_portsecurity.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # 3 | # check_portsecurity.pl - nagios plugin 4 | # 5 | # Port Security Status Nagios Plugin 6 | # 7 | # Copyright (c) 2011, Barry O'Donovan 8 | # All rights reserved. 9 | # 10 | # Redistribution and use in source and binary forms, with or without modification, 11 | # are permitted provided that the following conditions are met: 12 | # 13 | # * Redistributions of source code must retain the above copyright notice, this 14 | # list of conditions and the following disclaimer. 15 | # 16 | # * Redistributions in binary form must reproduce the above copyright notice, this 17 | # list of conditions and the following disclaimer in the documentation and/or 18 | # other materials provided with the distribution. 19 | # 20 | # * Neither the name of Open Solutions nor the names of its contributors may be 21 | # used to endorse or promote products derived from this software without 22 | # specific prior written permission. 23 | # 24 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 25 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 | # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 28 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 32 | # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 33 | # OF THE POSSIBILITY OF SUCH DAMAGE. 34 | # 35 | 36 | use strict; 37 | 38 | use Net::SNMP; 39 | use Getopt::Long; 40 | &Getopt::Long::config( 'auto_abbrev' ); 41 | 42 | my %ERRORS = ( 43 | 'OK' , 0, 44 | 'WARNING', 1, 45 | 'CRITICAL', 2, 46 | 'UNKNOWN', 3 47 | ); 48 | 49 | my %CISCO_PORTSECURITY_STATES = ( 50 | '1', 'SECUREUP', 51 | '2', 'SECUREDOWN', 52 | '3', 'SHUTDOWN' 53 | ); 54 | 55 | my %port_states = ( 56 | '1', 0, 57 | '2', 0, 58 | '3', 0 59 | ); 60 | 61 | my $status; 62 | my $TIMEOUT = 20; 63 | my $state = "OK"; 64 | my $answer = ""; 65 | my $snmpkey; 66 | my $community = "public"; 67 | my $port = 161; 68 | my $hostname = undef; 69 | my $session; 70 | my $error; 71 | my $response = undef; 72 | 73 | my $alertOnSecureDown = 0; 74 | 75 | my $verbose = 0; 76 | my $help = 0; 77 | 78 | # Just in case of problems, let's not hang Nagios 79 | $SIG{'ALRM'} = sub { 80 | print( "ERROR: No snmp response from $hostname\n" ); 81 | exit $ERRORS{"UNKNOWN"}; 82 | }; 83 | alarm( $TIMEOUT ); 84 | 85 | 86 | $status = GetOptions( 87 | "hostname=s", \$hostname, 88 | "community=s", \$community, 89 | "port=i", \$port, 90 | "verbose", \$verbose, 91 | "help|?", \$help, 92 | "alert-on-secure-down", \$alertOnSecureDown 93 | ); 94 | 95 | if( !$status || $help ) { 96 | usage(); 97 | } 98 | 99 | usage() if( !defined( $hostname ) ); 100 | 101 | ( $session, $error ) = Net::SNMP->session( 102 | -hostname => $hostname, 103 | -community => $community, 104 | -port => $port, 105 | -translate => 0 106 | ); 107 | 108 | if( !defined( $session ) ) 109 | { 110 | $state = 'UNKNOWN'; 111 | $answer = $error; 112 | print( "$state: $answer" ); 113 | exit $ERRORS{$state}; 114 | } 115 | 116 | 117 | 118 | my $snmpPortSecurityTable = '1.3.6.1.4.1.9.9.315.1.2.1.1.2'; 119 | my $snmpPortNameTable = '1.3.6.1.2.1.31.1.1.1.1'; 120 | my $snmpPortAliasTable = '1.3.6.1.2.1.31.1.1.1.18'; 121 | 122 | my $securityTable = snmpGetTable( $snmpPortSecurityTable, 'port security' ); 123 | my $nameTable = snmpGetTable( $snmpPortNameTable, 'port name' ); 124 | my $aliasTable = snmpGetTable( $snmpPortAliasTable, 'port alias' ); 125 | 126 | if( $securityTable && $nameTable && $aliasTable ) 127 | { 128 | foreach $snmpkey ( keys %{$securityTable} ) 129 | { 130 | if( $snmpkey =~ /$snmpPortSecurityTable\.(\d+)$/ ) 131 | { 132 | my $t_index = $1; 133 | 134 | my $t_state = $securityTable->{$snmpPortSecurityTable . '.' . $t_index}; 135 | my $t_name = $nameTable->{$snmpPortNameTable . '.' . $t_index}; 136 | my $t_alias = $aliasTable->{$snmpPortAliasTable . '.' . $t_index}; 137 | 138 | print( "Port Security for $t_name - $t_alias - $CISCO_PORTSECURITY_STATES{$t_state}\n" ) if $verbose; 139 | 140 | if( !defined( $port_states{$t_state} ) ) { 141 | $port_states{$t_state} = 0; 142 | } 143 | $port_states{$t_state}++; 144 | 145 | if( $t_state == 2 && $alertOnSecureDown ) { 146 | &setstate( 'WARNING', "Secure down alert for $t_name - $t_alias" ); 147 | } elsif( $t_state == 0 ) { 148 | &setstate( 'CRITICAL', "Shutdown alert for $t_name - $t_alias" ); 149 | } elsif( $t_state != 1 && $t_state != 2 ) { 150 | &setstate( 'WARNING', "Unknown port security state ($t_state) for $t_name - $t_alias" ); 151 | } 152 | } 153 | } 154 | } 155 | 156 | 157 | 158 | $session->close; 159 | 160 | if( $state eq 'OK' ) { 161 | print "OK - "; 162 | 163 | while( my ( $key, $value ) = each( %port_states ) ) { 164 | print "$value $CISCO_PORTSECURITY_STATES{$key}; "; 165 | } 166 | print "\n"; 167 | } 168 | else { 169 | print "$answer\n"; 170 | } 171 | 172 | exit $ERRORS{$state}; 173 | 174 | 175 | 176 | sub usage { 177 | printf "\nUsage:\n"; 178 | printf "\n"; 179 | printf "Perl Cisco port security plugin for Nagios\n\n"; 180 | printf "check_portsecurity.pl -c -p -h \n\n"; 181 | printf "Checks the operational status of the port security feature on an interface\n"; 182 | printf " secureup(1) - This indicates port security is operational.\n"; 183 | printf " securedown(2) - This indicates port security is not operational. This\n"; 184 | printf " happens when port security is configured to be enabled but could\n"; 185 | printf " not be enabled due to certain reasons such as conflict with other\n"; 186 | printf " features.\n"; 187 | printf " shutdown(3) - This indicates that the port is shutdown due to port\n"; 188 | printf " security violation when the object cpsIfViolationAction is of type\n"; 189 | printf " 'shutdown'.\n\n"; 190 | printf "Additional options:\n\n"; 191 | printf " --help This help message\n\n"; 192 | printf " --hostname The hostname to check\n"; 193 | printf " --port The port to query SNMP on (using: $port)\n"; 194 | printf " --community The SNMP access community (using: $community)\n\n"; 195 | printf " --alert-on-secure-down If port is in SECUREDOWN state, generate a warning alert\n\n"; 196 | printf "\nCopyright (c) 2011, Barry O'Donovan \n"; 197 | printf "All rights reserved.\n\n"; 198 | printf "This script comes with ABSOLUTELY NO WARRANTY\n"; 199 | printf "This programm is licensed under the terms of the "; 200 | printf "BSD New License (check source code for details)\n"; 201 | printf "\n\n"; 202 | 203 | exit $ERRORS{"UNKNOWN"} if !$help; 204 | exit 0; 205 | } 206 | 207 | sub setstate { 208 | my $newstate = shift( @_ ); 209 | my $message = shift( @_ ); 210 | 211 | if( $ERRORS{$newstate} > $ERRORS{$state} ) 212 | { 213 | $state = $newstate; 214 | } 215 | elsif( $newstate eq 'UNKNOWN' && $state eq 'OK' ) 216 | { 217 | $state = $newstate; 218 | } 219 | 220 | if( $answer ) { $answer .= "
\n"; } 221 | 222 | $answer .= $message; 223 | } 224 | 225 | sub snmpGetTable { 226 | my $oid = shift( @_ ); 227 | my $check = shift( @_ ); 228 | 229 | if( !defined( $response = $session->get_table( $oid ) ) ) 230 | { 231 | if( $session->error_status() == 2 || $session->error() =~ m/requested table is empty or does not exist/i ) 232 | { 233 | print "OID not supported for $check ($oid).\n" if $verbose; 234 | return 0; 235 | } 236 | 237 | $answer = $session->error(); 238 | $session->close; 239 | 240 | $state = 'CRITICAL'; 241 | print( "$state: $answer (in check for $check with OID: $oid)\n" ); 242 | exit $ERRORS{$state}; 243 | } 244 | 245 | return $response; 246 | } 247 | 248 | sub snmpGetRequest { 249 | my $oid = shift( @_ ); 250 | my $check = shift( @_ ); 251 | my $response; 252 | 253 | if( !defined( $response = $session->get_request( $oid ) ) ) 254 | { 255 | if( $session->error_status() == 2 || $session->error() =~ m/requested table is empty or does not exist/i ) 256 | { 257 | print "OID not supported for $check ($oid).\n" if $verbose; 258 | return 0; 259 | } 260 | 261 | $answer = $session->error(); 262 | $session->close; 263 | 264 | $state = 'CRITICAL'; 265 | print( "$state: $answer (in check for $check with OID: $oid)\n" ); 266 | exit $ERRORS{$state}; 267 | } 268 | 269 | return $response; 270 | } 271 | -------------------------------------------------------------------------------- /check_portstatus.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # 3 | # check_portsecurity.pl - nagios plugin 4 | # 5 | # Port Security Status Nagios Plugin 6 | # 7 | # Copyright (c) 2011, Barry O'Donovan 8 | # All rights reserved. 9 | # 10 | # Redistribution and use in source and binary forms, with or without modification, 11 | # are permitted provided that the following conditions are met: 12 | # 13 | # * Redistributions of source code must retain the above copyright notice, this 14 | # list of conditions and the following disclaimer. 15 | # 16 | # * Redistributions in binary form must reproduce the above copyright notice, this 17 | # list of conditions and the following disclaimer in the documentation and/or 18 | # other materials provided with the distribution. 19 | # 20 | # * Neither the name of Open Solutions nor the names of its contributors may be 21 | # used to endorse or promote products derived from this software without 22 | # specific prior written permission. 23 | # 24 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 25 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 | # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 28 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 32 | # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 33 | # OF THE POSSIBILITY OF SUCH DAMAGE. 34 | # 35 | 36 | use strict; 37 | 38 | use Net::SNMP; 39 | use Getopt::Long; 40 | &Getopt::Long::config( 'auto_abbrev' ); 41 | 42 | my %ERRORS = ( 43 | 'OK' , 0, 44 | 'WARNING', 1, 45 | 'CRITICAL', 2, 46 | 'UNKNOWN', 3 47 | ); 48 | 49 | my %CISCO_PORT_OPER_STATES = ( 50 | '1' => 'UP', 51 | '2' => 'DOWN', 52 | '3' => 'TESTING', 53 | '4' => 'UNKNOWN', 54 | '5' => 'DORMANT', 55 | '6' => 'NOT_PRESENT', 56 | '7' => 'LOWER_LAYER_DOWN' 57 | ); 58 | 59 | my %port_states; 60 | my %port_admin_states = ( 61 | '1' => 0, 62 | '2' => 0, 63 | '3' => 0 64 | ); 65 | 66 | my $window = 3600; 67 | my $sysuptime = 0; 68 | 69 | my $status; 70 | my $timeout = 20; 71 | my $state = "OK"; 72 | my $answer = ""; 73 | my $snmpkey; 74 | my $community = "public"; 75 | my $port = 161; 76 | my $snmpversion = '2c'; 77 | my $username = undef; 78 | my $authprotocol = 'sha1'; 79 | my $authpassword = undef; 80 | my $privprotocol = 'aes'; 81 | my $privpassword; 82 | 83 | my $hostname = undef; 84 | my $session; 85 | my $error; 86 | my $response = undef; 87 | my $ignoreregexp = undef; 88 | my $matchregexp = undef; 89 | 90 | my $allports = 0; 91 | 92 | my $verbose = 0; 93 | my $help = 0; 94 | 95 | $status = GetOptions( 96 | "hostname=s" => \$hostname, 97 | "community=s" => \$community, 98 | "port=i" => \$port, 99 | "verbose" => \$verbose, 100 | "all-ports" => \$allports, 101 | "help|?" => \$help, 102 | "window=i" => \$window, 103 | "ignoreregexp=s" => \$ignoreregexp, 104 | "matchregexp=s" => \$matchregexp, 105 | "snmpversion=s" => \$snmpversion, 106 | "username=s" => \$username, 107 | "authprotocol=s" => \$authprotocol, 108 | "authpassword=s" => \$authpassword, 109 | "privprotocol=s" => \$privprotocol, 110 | "privpassword=s" => \$privpassword, 111 | "timeout=i" => \$timeout, 112 | ); 113 | 114 | # Just in case of problems, let's not hang Nagios 115 | $SIG{'ALRM'} = sub { 116 | print( "ERROR: No snmp response from $hostname\n" ); 117 | exit $ERRORS{"UNKNOWN"}; 118 | }; 119 | alarm( $timeout ); 120 | 121 | if( !$status || $help ) { 122 | usage(); 123 | } 124 | 125 | 126 | usage() if( !defined( $hostname ) ); 127 | 128 | my @sessionargs = ( 129 | hostname => $hostname, 130 | port => $port, 131 | version => $snmpversion, 132 | translate => 0 133 | ); 134 | 135 | if ($snmpversion eq '3') { 136 | push @sessionargs, ( 137 | username => $username, 138 | authprotocol => $authprotocol, 139 | authpassword => $authpassword, 140 | privprotocol => $privprotocol, 141 | privpassword => $privpassword, 142 | ); 143 | } else { 144 | push @sessionargs, ( 145 | community => $community, 146 | ); 147 | } 148 | 149 | ($session, $error) = Net::SNMP->session(@sessionargs); 150 | 151 | if( !defined( $session ) ) 152 | { 153 | $state = 'UNKNOWN'; 154 | $answer = $error; 155 | print( "$state: $answer" ); 156 | exit $ERRORS{$state}; 157 | } 158 | 159 | 160 | 161 | if( !( $sysuptime = getSysUptime() ) ) { 162 | $state = 'UNKNOWN'; 163 | $answer = "Could not get system uptime"; 164 | print( "$state: $answer" ); 165 | exit $ERRORS{$state}; 166 | } 167 | 168 | printf( "System up time: %f\n", $sysuptime ) if $verbose; 169 | 170 | my $snmpPortOperStatusTable = '1.3.6.1.2.1.2.2.1.8'; 171 | my $snmpPortAdminStatusTable = '1.3.6.1.2.1.2.2.1.7'; 172 | my $snmpPortNameTable = '1.3.6.1.2.1.31.1.1.1.1'; 173 | my $snmpPortAliasTable = '1.3.6.1.2.1.31.1.1.1.18'; 174 | my $snmpPortTypeTable = '1.3.6.1.2.1.2.2.1.3'; 175 | my $snmpPortLastChangeTable = '1.3.6.1.2.1.2.2.1.9'; 176 | my $snmpPortChangeReasonTable = '1.3.6.1.4.1.9.9.276.1.1.2.1.3'; 177 | 178 | my $operStatus = snmpGetTable( $snmpPortOperStatusTable, 'port operational status' ); 179 | my $adminStatus = snmpGetTable( $snmpPortAdminStatusTable, 'port admin status' ); 180 | my $name = snmpGetTable( $snmpPortNameTable, 'port name' ); 181 | my $alias = snmpGetTable( $snmpPortAliasTable, 'port alias' ); 182 | my $type = snmpGetTable( $snmpPortTypeTable, 'port type' ); 183 | my $lastChange = snmpGetTable( $snmpPortLastChangeTable, 'port last change at' ); 184 | my $changeReason = snmpGetTable( $snmpPortChangeReasonTable, 'port change reason' ); 185 | 186 | if( $operStatus && $adminStatus && $name && $alias && $lastChange ) 187 | { 188 | foreach $snmpkey ( keys %{$name} ) 189 | { 190 | if( $snmpkey =~ /$snmpPortNameTable\.(\d+)$/ ) 191 | { 192 | my $t_index = $1; 193 | 194 | my $t_state = $operStatus->{$snmpPortOperStatusTable . '.' . $t_index}; 195 | my $t_admin = $adminStatus->{$snmpPortAdminStatusTable . '.' . $t_index}; 196 | my $t_name = $name->{$snmpPortNameTable . '.' . $t_index}; 197 | my $t_alias = $alias->{$snmpPortAliasTable . '.' . $t_index}; 198 | my $t_type = $type->{$snmpPortTypeTable . '.' . $t_index}; 199 | my $t_lastChange = $lastChange->{$snmpPortLastChangeTable . '.' . $t_index} / 100.0; 200 | my $t_changeReason = $changeReason->{$snmpPortChangeReasonTable . '.' . $t_index} if $changeReason; 201 | 202 | # we're not always interested in every port -> allow some to be ignored by regexp on description 203 | if( $ignoreregexp && $t_alias =~ /$ignoreregexp/ ) { 204 | next; 205 | } 206 | 207 | # Monitor only specific ports by means of regex on port description/alias. 208 | if( $matchregexp && $t_alias !~ /$matchregexp/ ) { 209 | next; 210 | } 211 | 212 | if( defined( $t_type ) && int( $t_type ) != 6 && !$allports ) 213 | { 214 | printf( "Skipping $t_name - $t_alias of type $t_type as only checking Ethernet ports\n" ) if $verbose; 215 | next; 216 | } 217 | 218 | if( !$t_changeReason ) { 219 | $t_changeReason = ''; 220 | } 221 | 222 | printf( "Port State for $t_name - $t_alias - $CISCO_PORT_OPER_STATES{$t_state} - changed %0.1f secs ago because $t_changeReason\n", ( $sysuptime - $t_lastChange ) ) if $verbose; 223 | 224 | if( !defined( $port_states{$t_state} ) ) { 225 | $port_states{$t_state} = 0; 226 | } 227 | $port_states{$t_state}++; 228 | 229 | if( !defined( $port_admin_states{$t_admin} ) ) { 230 | $port_admin_states{$t_admin} = 0; 231 | } 232 | $port_admin_states{$t_admin}++; 233 | 234 | if( ( $sysuptime - $t_lastChange ) <= $window && ( $sysuptime - $t_lastChange ) >= 0 ) { 235 | &setstate( 'WARNING', 236 | sprintf( "Port state change to $CISCO_PORT_OPER_STATES{$t_state} %0.1f mins ago for ${t_name} [DESC: ${t_alias}] [Reason: %s]. ", 237 | ( $sysuptime - $t_lastChange ) / 60.0, defined( $t_changeReason ) ? $t_changeReason : '' 238 | ) 239 | ); 240 | } 241 | } 242 | } 243 | } 244 | 245 | 246 | 247 | $session->close; 248 | 249 | if( $state eq 'OK' ) { 250 | print "OK - (oper/admin) "; 251 | 252 | while( my ( $key, $value ) = each( %port_states ) ) { 253 | printf( "%d%s %s; ", $value, defined( $port_admin_states{$key} ) ? "/$port_admin_states{$key}" : '', $CISCO_PORT_OPER_STATES{$key} ); 254 | } 255 | print "\n"; 256 | } 257 | else { 258 | print "$answer\n"; 259 | } 260 | 261 | exit $ERRORS{$state}; 262 | 263 | 264 | 265 | 266 | sub getSysUptime 267 | { 268 | my $snmpSysUpTime = '.1.3.6.1.2.1.1.3.0'; 269 | 270 | return 0 if( !( $response = snmpGetRequest( $snmpSysUpTime, 'system uptime' ) ) ); 271 | 272 | return $response->{$snmpSysUpTime} / 100.0; 273 | } 274 | 275 | 276 | sub usage { 277 | printf "\nUsage:\n"; 278 | printf "\n"; 279 | printf "Perl Cisco port status plugin for Nagios\n\n"; 280 | printf "check_portstatus.pl -c -p -h \n\n"; 281 | printf "Checks the operational status of the port and alerts if it changed within\n"; 282 | printf " \$window seconds ago (default: $window).\n\n"; 283 | printf "Additional options:\n\n"; 284 | printf " --help This help message\n\n"; 285 | printf " --hostname The hostname to check\n"; 286 | printf " --port The port to query SNMP on (using: $port)\n"; 287 | printf " --community The SNMP access community (using: $community)\n\n"; 288 | printf " --window If change occured within \$window seconds ago, then alert\n\n"; 289 | printf " --all-ports By default, we only examine Ethernet ports\n\n"; 290 | printf " --ignoreregex Ignore port descriptions using regex\n\n"; 291 | printf " --matchregex Match port descriptions using regex\n\n"; 292 | printf "\nCopyright (c) 2011, Barry O'Donovan \n"; 293 | printf "All rights reserved.\n\n"; 294 | printf "This script comes with ABSOLUTELY NO WARRANTY\n"; 295 | printf "This programm is licensed under the terms of the "; 296 | printf "BSD New License (check source code for details)\n"; 297 | printf "\n\n"; 298 | 299 | exit $ERRORS{"UNKNOWN"} if !$help; 300 | exit 0; 301 | } 302 | 303 | sub setstate { 304 | my $newstate = shift( @_ ); 305 | my $message = shift( @_ ); 306 | 307 | if( $ERRORS{$newstate} > $ERRORS{$state} ) 308 | { 309 | $state = $newstate; 310 | } 311 | elsif( $newstate eq 'UNKNOWN' && $state eq 'OK' ) 312 | { 313 | $state = $newstate; 314 | } 315 | 316 | # if( $answer ) { $answer .= "
\n"; } 317 | 318 | $answer .= $message; 319 | } 320 | 321 | sub snmpGetTable { 322 | my $oid = shift( @_ ); 323 | my $check = shift( @_ ); 324 | 325 | if( !defined( $response = $session->get_table( $oid ) ) ) 326 | { 327 | if( $session->error_status() == 2 || $session->error() =~ m/requested table is empty or does not exist/i ) 328 | { 329 | print "OID not supported for $check ($oid).\n" if $verbose; 330 | return 0; 331 | } 332 | 333 | $answer = $session->error(); 334 | $session->close; 335 | 336 | $state = 'CRITICAL'; 337 | print( "$state: $answer (in check for $check with OID: $oid)\n" ); 338 | exit $ERRORS{$state}; 339 | } 340 | 341 | return $response; 342 | } 343 | 344 | sub snmpGetRequest { 345 | my $oid = shift( @_ ); 346 | my $check = shift( @_ ); 347 | my $response; 348 | 349 | if( !defined( $response = $session->get_request( $oid ) ) ) 350 | { 351 | if( $session->error_status() == 2 || $session->error() =~ m/requested table is empty or does not exist/i ) 352 | { 353 | print "OID not supported for $check ($oid).\n" if $verbose; 354 | return 0; 355 | } 356 | 357 | $answer = $session->error(); 358 | $session->close; 359 | 360 | $state = 'CRITICAL'; 361 | print( "$state: $answer (in check for $check with OID: $oid)\n" ); 362 | exit $ERRORS{$state}; 363 | } 364 | 365 | return $response; 366 | } 367 | -------------------------------------------------------------------------------- /check_processes_snmp.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # 3 | # check_processes_snmp.pl - nagios plugin 4 | # 5 | # nagios: -epn 6 | # 7 | # Process Check via SNMP 8 | # 9 | # Copyright (c) 2012, Barry O'Donovan 10 | # All rights reserved. 11 | # 12 | # Redistribution and use in source and binary forms, with or without modification, 13 | # are permitted provided that the following conditions are met: 14 | # 15 | # * Redistributions of source code must retain the above copyright notice, this 16 | # list of conditions and the following disclaimer. 17 | # 18 | # * Redistributions in binary form must reproduce the above copyright notice, this 19 | # list of conditions and the following disclaimer in the documentation and/or 20 | # other materials provided with the distribution. 21 | # 22 | # * Neither the name of Open Solutions nor the names of its contributors may be 23 | # used to endorse or promote products derived from this software without 24 | # specific prior written permission. 25 | # 26 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 27 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 28 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 | # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 30 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 31 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 33 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 34 | # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 35 | # OF THE POSSIBILITY OF SUCH DAMAGE. 36 | # 37 | 38 | use strict; 39 | 40 | use Net::SNMP; 41 | use Getopt::Long; 42 | &Getopt::Long::config( 'auto_abbrev' ); 43 | use Pod::Usage; 44 | 45 | my %ERRORS = ( 46 | 'UNSET', -1, 47 | 'OK' , 0, 48 | 'WARNING', 1, 49 | 'CRITICAL', 2, 50 | 'UNKNOWN', 3 51 | ); 52 | 53 | my $status; 54 | my $timeout = 20; 55 | my $state = "UNSET"; 56 | my $answer = ""; 57 | my $int; 58 | my $snmpkey; 59 | my $key; 60 | my $community = "public"; 61 | my $port = 161; 62 | my $snmpversion = '2c'; 63 | my $username = undef; 64 | my $authprotocol = 'sha1'; 65 | my $authpassword = undef; 66 | my $privprotocol = 'aes'; 67 | my $privpassword; 68 | 69 | my $hostname = undef; 70 | my $session; 71 | my $error; 72 | my $response = undef; 73 | 74 | my $procstats = ""; 75 | 76 | my $usage; 77 | my $verbose = 0; 78 | my $help = 0; 79 | my $manpage = 0; 80 | 81 | $status = GetOptions( 82 | "hostname=s" => \$hostname, 83 | "community=s" => \$community, 84 | "port=i" => \$port, 85 | "verbose" => \$verbose, 86 | "help|?" => \$help, 87 | "man" => \$manpage, 88 | "snmpversion=s" => \$snmpversion, 89 | "username=s" => \$username, 90 | "authprotocol=s" => \$authprotocol, 91 | "authpassword=s" => \$authpassword, 92 | "privprotocol=s" => \$privprotocol, 93 | "privpassword=s" => \$privpassword, 94 | "timeout=i" => \$timeout, 95 | ); 96 | 97 | # Just in case of problems, let's not hang Nagios 98 | $SIG{'ALRM'} = sub { 99 | print( "ERROR: No snmp response from $hostname\n" ); 100 | exit $ERRORS{"UNKNOWN"}; 101 | }; 102 | alarm( $timeout ); 103 | 104 | pod2usage(-verbose => 2) if $manpage; 105 | 106 | pod2usage( -verbose => 1 ) if $help; 107 | 108 | pod2usage() if !$status || !$hostname; 109 | 110 | my @sessionargs = ( 111 | hostname => $hostname, 112 | port => $port, 113 | version => $snmpversion, 114 | translate => 0 115 | ); 116 | 117 | if ($snmpversion eq '3') { 118 | push @sessionargs, ( 119 | username => $username, 120 | authprotocol => $authprotocol, 121 | authpassword => $authpassword, 122 | privprotocol => $privprotocol, 123 | privpassword => $privpassword, 124 | ); 125 | } else { 126 | push @sessionargs, ( 127 | community => $community, 128 | ); 129 | } 130 | 131 | ($session, $error) = Net::SNMP->session(@sessionargs); 132 | 133 | if( !defined( $session ) ) 134 | { 135 | $state = 'UNKNOWN'; 136 | $answer = $error; 137 | print( "$state: $answer" ); 138 | exit $ERRORS{$state}; 139 | } 140 | 141 | checkProcesses(); 142 | 143 | $session->close; 144 | 145 | if( $state eq 'OK' ) { 146 | print "OK - $procstats\n"; 147 | } 148 | else { 149 | print "$answer\n"; 150 | } 151 | 152 | exit $ERRORS{$state}; 153 | 154 | 155 | 156 | 157 | 158 | 159 | sub checkProcesses 160 | { 161 | my $snmpProcessTable = '.1.3.6.1.4.1.2021.2.1'; 162 | 163 | my $prName = $snmpProcessTable . '.2'; 164 | my $prMin = $snmpProcessTable . '.3'; 165 | my $prMax = $snmpProcessTable . '.4'; 166 | my $prCount = $snmpProcessTable . '.5'; 167 | my $prErrorFlag = $snmpProcessTable . '.100'; 168 | my $prErrMessage = $snmpProcessTable . '.101'; 169 | 170 | return if( !( $response = snmpGetTable( $snmpProcessTable, 'process table' ) ) ); 171 | 172 | $state = 'OK'; 173 | 174 | foreach $snmpkey ( keys %{$response} ) 175 | { 176 | # check each process 177 | $snmpkey =~ /$prName/ && do { 178 | 179 | if( $snmpkey =~ /$prName\.(\d+)$/ ) 180 | { 181 | my $t_index = $1; 182 | 183 | my $t_name = $response->{$prName . '.' . $t_index}; 184 | my $t_min = $response->{$prMin . '.' . $t_index}; 185 | my $t_max = $response->{$prMax . '.' . $t_index}; 186 | my $t_count = $response->{$prCount . '.' . $t_index}; 187 | my $t_err_flag = $response->{$prErrorFlag . '.' . $t_index}; 188 | my $t_err_msg = $response->{$prErrMessage . '.' . $t_index}; 189 | 190 | my $errormsg = defined ($t_err_msg) ? "[$t_err_msg]" : ""; 191 | 192 | print( "Process: $t_name $t_min <= $t_count <= $t_max => Err: $t_err_flag $errormsg\n" ) if $verbose; 193 | 194 | $procstats .= sprintf( "%s (%d<=%d<=%d); ", $t_name, $t_min, $t_count, $t_max ); 195 | 196 | if( $t_err_flag ) 197 | { 198 | if( $t_count == 0 && $t_min != 0 ) { 199 | &setstate( 'CRITICAL', "$t_name not running $errormsg" ); 200 | } elsif( $t_count < $t_min ) { 201 | &setstate( 'WARNING', "Too few $t_name running (${t_min} <= ${t_count} <= ${t_max}) $errormsg" ); 202 | } else { 203 | &setstate( 'WARNING', "Too many $t_name running (${t_min} <= ${t_count} <= ${t_max}) $errormsg" ); 204 | } 205 | } 206 | } 207 | } 208 | } 209 | } 210 | 211 | 212 | 213 | sub setstate { 214 | my $newstate = shift( @_ ); 215 | my $message = shift( @_ ); 216 | 217 | if( $ERRORS{$newstate} > $ERRORS{$state} ) 218 | { 219 | $state = $newstate; 220 | } 221 | elsif( $newstate eq 'UNKNOWN' && $state eq 'OK' ) 222 | { 223 | $state = $newstate; 224 | } 225 | 226 | if( $answer ) { $answer .= "
\n"; } 227 | 228 | $answer .= $message; 229 | } 230 | 231 | sub snmpGetTable { 232 | my $oid = shift( @_ ); 233 | my $check = shift( @_ ); 234 | 235 | if( !defined( $response = $session->get_table( $oid ) ) ) 236 | { 237 | if( $session->error_status() == 2 || $session->error() =~ m/requested table is empty or does not exist/i ) 238 | { 239 | print "OID not supported for $check ($oid).\n" if $verbose; 240 | return 0; 241 | } 242 | 243 | $answer = $session->error(); 244 | $session->close; 245 | 246 | $state = 'CRITICAL'; 247 | print( "$state: $answer (in check for $check with OID: $oid)\n" ); 248 | exit $ERRORS{$state}; 249 | } 250 | 251 | return $response; 252 | } 253 | 254 | 255 | __END__ 256 | 257 | =head1 check_processes_snmp.pl 258 | 259 | check_processes_snmp.pl - Nagios plugin to check processes via SNMP as defined in SNMP 260 | 261 | =head1 SYNOPSIS 262 | 263 | check_processes_snmp.pl --hostname [options] 264 | 265 | Options: 266 | --hostname the hostname or IP of the server to check 267 | --port the port to query for SNMP 268 | --community the SNMP community to use 269 | --verbose display additional information 270 | --help extended help message 271 | --man full manual page 272 | --snmpversion specify the SNMP version (2c or 3) 273 | --username specify the SNMPv3 username 274 | --authprotocol specify the SNMPv3 authentication protocol 275 | --authpassword specify the SNMPv3 authentication username 276 | --privprotocol specify the SNMPv3 privacy protocol 277 | --privpassword specify the SNMPv3 privacy username 278 | 279 | =head1 OPTIONS AND ARGUMENTS 280 | 281 | =over 8 282 | 283 | =item B<--verbose> 284 | 285 | Print additional information including all disks found and their usage states. 286 | 287 | =item B<--help> 288 | 289 | Expanded help message. 290 | 291 | =item B<--man> 292 | 293 | Full manual page. 294 | 295 | =back 296 | 297 | =head1 DESCRIPTION 298 | 299 | B will read all process entries via SNMP on the given host 300 | and issue a warning for too many / too few processes running or critical alert if 0 301 | processes are running (and min != 0) 302 | 303 | =head2 CONFIGURING YOUR SNMP DAEMON 304 | 305 | This script requires that you have configured your SNMP daemon to provide process 306 | information. The typical snmpd.conf configuration (for bsnmpd) would be: 307 | 308 | prNames.2 = "sendmail" 309 | prMin.2 = 1 310 | prMax.2 = 5 311 | 312 | =head1 AUTHOR 313 | 314 | Written by Barry O'Donovan as part of the work we 315 | do in Open Solutions (http://www.opensolutions.ie/). 316 | 317 | =head1 COPYRIGHT 318 | 319 | Copyright (c) 2012, Barry O'Donovan . 320 | All rights reserved. 321 | 322 | Released under the terms of the modified BSD license. 323 | See http://opensource.org/licenses/alphabetical for full text. 324 | 325 | =head1 SEE ALSO 326 | 327 | https://github.com/barryo/nagios-plugins 328 | 329 | =cut 330 | -------------------------------------------------------------------------------- /check_radius.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Barry O'Donovan - 20160711 4 | 5 | # Copyright (c) 2004 - 2016, Barry O'Donovan 6 | # All rights reserved. 7 | # 8 | # Redistribution and use in source and binary forms, with or without modification, 9 | # are permitted provided that the following conditions are met: 10 | # 11 | # * Redistributions of source code must retain the above copyright notice, this 12 | # list of conditions and the following disclaimer. 13 | # 14 | # * Redistributions in binary form must reproduce the above copyright notice, this 15 | # list of conditions and the following disclaimer in the documentation and/or 16 | # other materials provided with the distribution. 17 | # 18 | # * Neither the name of Open Solutions nor the names of its contributors may be 19 | # used to endorse or promote products derived from this software without 20 | #  specific prior written permission. 21 | #  22 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 23 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 | # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 26 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 30 | # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | # OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | 34 | RADCLIENT=$(which radclient) 35 | 36 | if [ $? -ne 0 ] || [ ! -x $RADCLIENT ]; then 37 | echo UNKNOWN: You need to install FreeRADIUS client utilities 38 | exit 3 39 | fi 40 | 41 | username="" 42 | password="" 43 | server="" 44 | port=1812 45 | secret="" 46 | 47 | function show_help { 48 | echo -n "USAGE: " 49 | echo -n ${0##*/} 50 | echo " -u username -p password -s radius_server -c shared_secret [-i port (1812)]" 51 | } 52 | 53 | OPTIND=1 # Reset in case getopts has been used previously in the shell. 54 | 55 | while getopts "h?u:p:s:i:c:" opt; do 56 | case "$opt" in 57 | h|\?) 58 | show_help 59 | exit 0 60 | ;; 61 | u) 62 | username=$OPTARG 63 | ;; 64 | p) 65 | password=$OPTARG 66 | ;; 67 | s) 68 | server=$OPTARG 69 | ;; 70 | i) 71 | port=$OPTARG 72 | ;; 73 | c) 74 | secret=$OPTARG 75 | ;; 76 | esac 77 | done 78 | 79 | if [ -z $username ] || [ -z $password ] || [ -z $server ] || [ -z $port ] || [ -z $secret ]; then 80 | show_help 81 | echo You tried: -u $username -p $password -s $server -i $port -c $secret 82 | exit 3 83 | fi 84 | 85 | 86 | echo "User-Name=${username},User-Password=${password}" | radclient -r 1 -t 2 ${server}:${port} auth ${secret} >/dev/null 2>&1 87 | 88 | if [ $? -eq 0 ]; then 89 | echo "OK: RADIUS authentication request successful" 90 | exit 0; 91 | fi 92 | 93 | echo "CRITICAL: RADIUS authentication failed" 94 | exit 2 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /notify-by-pushover.php: -------------------------------------------------------------------------------- 1 | #! /usr/local/bin/php 2 | 51 | */ 52 | 53 | 54 | // This script sends Nagios plugins to Pushover 55 | // 56 | // See: http://www.barryodonovan.com/index.php/2013/05/31/nagios-icinga-alerts-via-pushover 57 | // 58 | // USAGE: notify-by-pushover.php 59 | 60 | 61 | date_default_timezone_set('Europe/Dublin'); 62 | define( "VERSION", '1.0.0' ); 63 | 64 | ini_set( 'max_execution_time', '55' ); 65 | 66 | ini_set( 'display_errors', true ); 67 | ini_set( 'display_startup_errors', true ); 68 | 69 | define( 'PO_PRI_LOW', -1 ); 70 | define( 'PO_PRI_NORMAL', 0 ); 71 | define( 'PO_PRI_HIGH', 1 ); 72 | define( 'PO_PRI_EMERG', 2 ); // not used at present in this script 73 | 74 | 75 | // get the message from STDIN 76 | $message = trim( fgets( STDIN ) ); 77 | 78 | // get the parameters 79 | 80 | $mode = isset( $argv[1] ) ? $argv[1] : false; // SERVICE or HOST 81 | $app = isset( $argv[2] ) ? $argv[2] : false; 82 | $user = isset( $argv[3] ) ? $argv[3] : false; 83 | $type = isset( $argv[4] ) ? $argv[4] : false; // NOTIFICATIONTYPE 84 | $state = isset( $argv[5] ) ? $argv[5] : false; // STATE 85 | 86 | if( !$mode || !$app || !$user || !$type || !$state ) 87 | die( "ERROR - USAGE: notify-by-pushover.php \n\n" ); 88 | 89 | switch( $state ) 90 | { 91 | case 'WARNING': 92 | case 'UNKNOWN': 93 | $priority = PO_PRI_LOW; 94 | break; 95 | 96 | case 'OK': 97 | $priority = PO_PRI_NORMAL; 98 | break; 99 | 100 | case 'DOWN': 101 | case 'CRITICAL': 102 | $priority = PO_PRI_HIGH; 103 | break; 104 | 105 | default: 106 | $priority = PO_PRI_NORMAL; 107 | break; 108 | } 109 | 110 | curl_setopt_array( $ch = curl_init(), array( 111 | CURLOPT_URL => "https://api.pushover.net/1/messages.json", 112 | CURLOPT_RETURNTRANSFER => true, 113 | CURLOPT_POSTFIELDS => array( 114 | "token" => $app, 115 | "user" => $user, 116 | "message" => $message, 117 | "title" => "Nagios Alert - $mode - $type - $state", 118 | "priority" => $priority 119 | ) 120 | )); 121 | 122 | curl_exec($ch); 123 | curl_close($ch); 124 | 125 | 126 | 127 | 128 | --------------------------------------------------------------------------------