Compare commits

..

10 Commits

Author SHA1 Message Date
c39cd60d85 renamed for Gitea 2026-01-02 12:38:15 +01:00
ea7c02e270 updated readme to state the python3 is now required 2024-12-29 15:41:12 +01:00
c1cfdd7d21 updated plugins to python3
made specifying which temperatur for plugins/check_temperature mandatory
2024-12-29 15:36:33 +01:00
bbad51d9ca 2 optimizations:
- got rid of unnecessary read commands to set variables
- de-duplicate the list of nameservers to check before checking
2021-03-09 23:30:46 +01:00
dadb9bb181 First commit for check_dns_replication 2021-03-09 21:48:55 +01:00
302f2b0ade Fixed layout issues in GitLab 2019-03-10 13:12:51 +01:00
3128d9ae02 Minor updates to README.md 2019-03-10 13:04:44 +01:00
1ec60af44a Updated documentation 2019-03-10 13:03:10 +01:00
379482e729 Added Bosch Sensortec I2C BME280/BMP280 sensor
Added support for additional measurements in addition to the temperature
Fixed handling of default I2C address
Updated documentation for the new I2C sensors (and fixed a few errors)
2019-03-10 13:01:49 +01:00
Frederik Lindenaar
28daf07d1a fixed scaling issue for Raspberry Pi CPU temperature 2019-03-03 20:47:38 +01:00
5 changed files with 515 additions and 114 deletions

182
README.md
View File

@@ -9,15 +9,19 @@ not really appropriate. I am publishing them separately so that others may
benefit from these as well. Use them freely and please let me know is you benefit from these as well. Use them freely and please let me know is you
encounter any issues or require changes. encounter any issues or require changes.
The latest versions, documentation and bugtracker available on my Please note: as of December 2024 python scripts were upgraded to python3
[GitLab instance](https://gitlab.lindenaar.net/scripts/privacyidea-checkotp)
Copyright (c) 2015 - 2016 Frederik Lindenaar. free for distribution under The latest versions, documentation and bugtracker available on my
[GitLab instance](https://gitlab.lindenaar.net/scripts/nagios-plugins)
Copyright (c) 2015 - 2024 Frederik Lindenaar. free for distribution under
the GNU General Public License, see [below](#license) the GNU General Public License, see [below](#license)
contents contents
======== ========
This repository contains the following scripts: This repository contains the following scripts:
* [check_dns_replication](#check_dns_replication)
check DNS zone replication by comparing zone serial numbers on DNS servers
* [check_memory](#check_memory) * [check_memory](#check_memory)
patched version of nagios-plugins check_memory script for Linux procps v3.3+ patched version of nagios-plugins check_memory script for Linux procps v3.3+
* [check_multiple_host_addresses](#host_addresses) * [check_multiple_host_addresses](#host_addresses)
@@ -25,10 +29,71 @@ This repository contains the following scripts:
* [check_otp](#check_otp) * [check_otp](#check_otp)
plugin to monitor PrivacyIDEA (and LinOTP) OTP validation plugin to monitor PrivacyIDEA (and LinOTP) OTP validation
* [check_temperature](#check_temperature) * [check_temperature](#check_temperature)
plugin to monitor the CPU temperature of a RaspberryPi or that of a DS18b20 1-wire sensor on a RaspberryPi plugin to monitor the RaspberryPi CPU temperature or that of an 1-wire
(DS18b20) or I2C (MCP9080) sensor attached to a RaspberryPi
* [nagiosstatus](#nagiosstatus) * [nagiosstatus](#nagiosstatus)
CGI-BIN script to report the status of nagios (to monitor nagios itself) CGI-BIN script to report the status of nagios (to monitor nagios itself)
<a name=check_dns_replication>plugins/check_dns_replication</a>
---------------------------------------------------------------
With this check plugin / script, Nagios can monitor the replication of DNS zones
between the authoritative DNS server for a domain and one or more of it's slave
(or secondary) DNS servers. The script can check one or multiple DNS zones and
can be pointed at one ore more specific DNS slave server(s) or us the NS records
of the zone to check all DNS servers of that domain (or a combination of this)
The script expects a (comma separated list of) DNS zone(s) to validate as its
first command line parameter. It optionally also accepts one or more DNS servers
to check as further parameters (either separate parameters or comma separated).
If no DNS Servers are provided or the `-n` command line option is passed it will
lookup the DNS Servers from the NS records in de DNS zone.
The script will first fetch the authoritative DNS server from the SOA record, so
that server must be reachable. This first lookup will be done against the first
DNS server, if provided, or the default nameserver of the host. Next it will
fetch the DNS zone's SOA record from each server and compare it with the master.
Installation is straightforward, after installing the script on your server, add
the following to your `commands.cmd` configuration file to make it available:
~~~
# 'check-dns-replication' command definition to check DNS replication of one or more zones
define command {
command_name check-dns-replication
command_line [install_path]/plugins/check_dns_replication -n '$ARG1$' '$HOSTADDRESS$'
}
# 'check-dns-slave' command to check DNS replication of one or more zones against a single server
define command {
command_name check-dns-slave
command_line [install_path]/plugins/check_dns_replication '$ARG1$' '$HOSTADDRESS$'
}
~~~
The example below shows how to check DNS zone replication for the primary DNS
server (which checks replication to all secondaries) and how to check an extra
secondary DNS server that is not listed as NS record in the zone.
~~~
# check DNS replication for an DNS zone to ensure all secondaries are in sync
define service {
host auth.dns.mydomain.tld
service_description DNS Zone Replication
check_command check-dns-replication!mydomain.tld
use generic-service
}
# check DNS replication to a specific secondary DNS server
define service {
host sec1.dns.mydomain.tld
service_description DNS Zone Replication to secondary
check_command check-dns-slave!mydomain.tld
use generic-service
}
~~~
<a name=check_memory>plugins/check_memory</a> <a name=check_memory>plugins/check_memory</a>
--------------------------------------------- ---------------------------------------------
Nagios check script to monitor the memory on Linux systems. Due to changes in Nagios check script to monitor the memory on Linux systems. Due to changes in
@@ -239,68 +304,128 @@ define service {
------------------------------------------------------- -------------------------------------------------------
Plugin (check) to monitor monitor the Raspberry Pi CPU temperature or that of a Plugin (check) to monitor monitor the Raspberry Pi CPU temperature or that of a
temperature sensor connected to a RaspberryPi. This implementation currently temperature sensor connected to a RaspberryPi. This implementation currently
supports the DS18B20 1-wire temperature sensor. Other methods and interfaces can supports the following sensors:
be plugged in easily (just raise a request or provide a patch). For information * 1-wire:
on how to connect sensor to the RaspberryPi and to get it working please see * Maxim Integrated [DS18B20](https://learn.adafruit.com/adafruits-raspberry-pi-lesson-11-ds18b20-temperature-sensing)
[this Adafruit tutorial]( * I2C
https://learn.adafruit.com/adafruits-raspberry-pi-lesson-11-ds18b20-temperature-sensing). * Bosch Sensortec [BME280](https://learn.adafruit.com/adafruit-bme280-humidity-barometric-pressure-temperature-sensor-breakout)
* Bosch Sensortec [BMP280](https://learn.adafruit.com/adafruit-bmp280-barometric-pressure-plus-temperature-sensor-breakout)
* Microchip [MCP9080](https://learn.adafruit.com/adafruit-mcp9808-precision-i2c-temperature-sensor-guide)
Other methods and interfaces can be plugged in easily (just raise a request or
provide a patch). For information on how to connect sensor to the RaspberryPi
and to get it working please click on the links in the list above. As per these,
most sensors require some configuration to make them available:
* No setup is required to read the CPU temperature.
* To enable 1-wire interface support on the RaspberryPi use the command:
No setup is required to read the CPU temperature. To enable the 1-wire interface
support on the RaspberryPi one can use the command:
~~~ ~~~
sudo raspi-config nonint do_onewire 0 sudo raspi-config nonint do_onewire 0
~~~ ~~~
or use `raspi-config` in interactive mode (9. Advanced Options --> A9. 1-Wire).
or use `raspi-config` interactively (1. Interfacing Options --> P7. 1-Wire).
Please note that changing this requires a reboot. Please note that changing this requires a reboot.
Installation for is straightforward, after installing the script on the server * To enable I2C interface support on the RaspberryPi use the command:
add the following to your Nagios `commands.cmd` configuration file:
~~~
sudo raspi-config nonint do_i2c 0
~~~
or use `raspi-config` interactively (1. Interfacing Options --> P5. I2C).
Please note that changing this requires a reboot.
The I2C interface also requires the `SMBus` or `SMBus2` library, to install
the `SMBus` library on Raspbian Linux run:
~~~
sudo apt install python-smbus
~~~
`SMBus2` is a pure Python implementation that requires system-wide or a
`virtualenv`-based installation, less trivial than installing the package.
Configuration of Nagios to use the script is straightforward, after installing
the script on the server add the following to your Nagios `commands.cmd`
configuration file to enable checking the CPU temperature:
~~~ ~~~
# 'check_cpu_temperature' command definition to monitor CPU temperature in C # 'check_cpu_temperature' command definition to monitor CPU temperature in C
# parameters: warning (ARG1) and critical (ARG2) temperature in Celcius # parameters: warning (ARG1) and critical (ARG2) temperature in Celcius
define command { define command {
command_name check_temperature command_name check_cpu_temperature
command_line [install_path]/plugins/check_temperature -w $ARG1$ -c $ARG2$ rpi_cpu command_line [install_path]/plugins/check_temperature -w $ARG1$ -c $ARG2$ rpi_cpu
} }
# 'check_cpu_ftemperature' command definition to monitor CPU temperature in F # 'check_cpu_ftemperature' command definition to monitor CPU temperature in F
# parameters: warning (ARG1) and critical (ARG2) temperature in Celcius # parameters: warning (ARG1) and critical (ARG2) temperature in Celcius
define command { define command {
command_name check_temperature command_name check_cpu_ftemperature
command_line [install_path]/plugins/check_temperature -F -w $ARG1$ -c $ARG2$ rpi_cpu command_line [install_path]/plugins/check_temperature -F -w $ARG1$ -c $ARG2$ rpi_cpu
} }
~~~
To monitor a supported temperature sensor on its default address, add:
~~~
# 'check_temperature' command definition to monitor a single temperature in C # 'check_temperature' command definition to monitor a single temperature in C
# parameters: warning (ARG1) and critical (ARG2) temperature in Celcius # parameters: warning (ARG1) and critical (ARG2) temperature in Celcius
define command { define command {
command_name check_temperature command_name check_cpu_temperature
command_line [install_path]/plugins/check_temperature -w $ARG1$ -c $ARG2$ w1_ds18b20 command_line [install_path]/plugins/check_temperature -w $ARG1$ -c $ARG2$ <<sensor>>
} }
# 'check_ftemperature' command definition to monitor a single temperature in F # 'check_ftemperature' command definition to monitor a single temperature in F
# parameters: warning (ARG1) and critical (ARG2) temperature in Farenheit # parameters: warning (ARG1) and critical (ARG2) temperature in Farenheit
define command { define command {
command_name check_ftemperature command_name check_cpu_temperature_f
command_line [install_path]/plugins/check_temperature -F -w $ARG1$ -c $ARG2$ w1_ds18b20 command_line [install_path]/plugins/check_temperature -F -w $ARG1$ -c $ARG2$ <<sensor>>
} }
~~~
With `<<sensor>>` replaced by the sensor, e.g. w1_ds18b20 for a 1-wire DS18B20,
i2c_mcp9808 for an I2C MCP9808 sensor or i2c_bme280 for an I2C BME280. Run
`check_temperature -h` to get the list of supported sensors. In case you have
multiple sensors, add a separate definition for each sensor with a different
value for `command_name`.
If you need to pass on additional parameters, e.g. the sensor serial for an
1-wire DS18B20, you can do that like this:
~~~
# 'check_temperature_sensor' command definition to monitor a single temperature in C # 'check_temperature_sensor' command definition to monitor a single temperature in C
# parameters: sensor serial (ARG1), warning (ARG2) and critical (ARG3) temperature in Celcius # parameters: sensor serial (ARG1), warning (ARG2) and critical (ARG3) temperature in Celcius
define command { define command {
command_name check_temperature_sensor command_name check_ds18b20_sensor
command_line [install_path]/plugins/check_temperature -w $ARG2$ -c $ARG3$ w1_ds18b20 -s $ARG1$ command_line [install_path]/plugins/check_temperature -w $ARG2$ -c $ARG3$ w1_ds18b20 -s $ARG1$
} }
# 'check_ftemperature_sensor' command definition to monitor a single temperature in F # 'check_ftemperature_sensor' command definition to monitor a single temperature in F
# parameters: sensor serial (ARG1), warning (ARG2) and critical (ARG3) temperature in Farenheit # parameters: sensor serial (ARG1), warning (ARG2) and critical (ARG3) temperature in Farenheit
define command { define command {
command_name check_ftemperature_sensor command_name check_ds18b20_sensor_f
command_line [install_path]/plugins/check_temperature -F -w $ARG2$ -c $ARG3$ w1_ds18b20 -s $ARG1$ command_line [install_path]/plugins/check_temperature -F -w $ARG2$ -c $ARG3$ w1_ds18b20 -s $ARG1$
} }
~~~ ~~~
Likewise, to pass the I2C address for an I2C MCP9808 use something like:
~~~
# 'check_temperature_sensor' command definition to monitor a single temperature in C
# parameters: sensor address (ARG1), warning (ARG2) and critical (ARG3) temperature in Celcius
define command {
command_name check_mcp9808_sensor
command_line [install_path]/plugins/check_temperature -w $ARG2$ -c $ARG3$ i2c_mcp9808 -a $ARG1$
}
# 'check_ftemperature_sensor' command definition to monitor a single temperature in F
# parameters: sensor address (ARG1), warning (ARG2) and critical (ARG3) temperature in Farenheit
define command {
command_name check_mcp9808_sensor_f
command_line [install_path]/plugins/check_temperature -F -w $ARG2$ -c $ARG3$ i2c_mcp9808 -a $ARG1$
}
~~~
For the list of supported sensors run `check_temperature -h` and to get the
options sensor ``<<sensor>>`` supports run `check_temperature <<sensor>> -h`.
Make sure to replace `[install_path]/plugins` with the location of the script. Make sure to replace `[install_path]/plugins` with the location of the script.
To use the it define a service check like below: To use the it define a service check like below:
@@ -313,7 +438,7 @@ define service {
use generic-service use generic-service
} }
# check temperature in Celcius using a DS18B20 sensor connected to a RaspberryPi # check temperature in Celcius using a sensor connected to a RaspberryPi
define service { define service {
host hostname.mydomain.tld host hostname.mydomain.tld
service_description Check Temperature service_description Check Temperature
@@ -325,7 +450,15 @@ define service {
define service { define service {
host hostname.mydomain.tld host hostname.mydomain.tld
service_description Check Temperature service_description Check Temperature
check_command check_temperature_sensor!0000a31ea3de!30!35 check_command check_ds18b20_sensor!0000a31ea3de!30!35
use generic-service
}
# check temperature with MCP9808 sensor 0x19 connected to a RaspberryPi
define service {
host hostname.mydomain.tld
service_description Check Temperature
check_command check_mcp9808_sensor!0x19!30!35
use generic-service use generic-service
} }
~~~ ~~~
@@ -362,4 +495,3 @@ General Public License for more details.
You should have received a copy of the GNU General Public License along with You should have received a copy of the GNU General Public License along with
this program. If not, download it from <http://www.gnu.org/licenses/>. this program. If not, download it from <http://www.gnu.org/licenses/>.

103
plugins/check_dns_replication Executable file
View File

@@ -0,0 +1,103 @@
#!/bin/bash
# check_dns_replication - check DNS zone replication by comparing zone serials
#
# Version 1.0, latest version, documentation and bugtracker available at:
# https://gitlab.lindenaar.net/scripts/nagios-plugins
#
# Copyright (c) 2021 Frederik Lindenaar
#
# This script is free software: you can redistribute and/or modify it under the
# terms of version 3 of the GNU General Public License as published by the Free
# Software Foundation, or (at your option) any later version of the license.
#
# This script is distributed in the hope that it will be useful but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, visit <http://www.gnu.org/licenses/> to download it.
# Usage: check_dns_replication [-n] dns_zone[,dns_zone...] [dns_server...]
if [ "$#" -eq 0 -o "$1" == "-n" -a "$#" -eq 1 ]; then
echo "DNSREPLICATION: UNKNOWN | missing parameter dns_zone"
exit 3
elif [ "$1" == "-n" ]; then
DNS_SERVER_LOOKUP=$1
shift
elif [ $1 == '-h' -o $1 == '--help' ]; then
cat << EOT
`basename $0` - check DNS zone replication by comparing SOA serial(s)
usage: $0 [-n] dns_zone[,dns_zone...] [dns_server...]
parameters:
-n when specified (or no dns_server provided) check domain's NS records
-h this help
dns_zone[,dns_zone...] list of DNS zones to check (comma separated!)
[dns_server...] DNS server(s) to compare with authoratative server
EOT
exit 3
elif [[ "$1" = -* ]]; then
echo "DNSREPLICATION: UNKNOWN | invalid parameter, for help run $0 -h"
exit 3
fi
DNS_ZONES=${1//,/ }
shift
DNS_SERVERS=${*//,/ }
n="
"
NAGIOS_STATE=OK
NAGIOS_RESULT=0
NAGIOS_DETAILS=
for DNS_ZONE in $DNS_ZONES; do
AUTH_NAMESERVER=$(host -t soa $DNS_ZONE ${DNS_SERVERS// .*/} | tail -1 | cut -d\ -f5 | sed "s/.$//")
[ -n "$AUTH_NAMESERVER" ] && AUTH_SOA_SERIAL=$(host -t soa $DNS_ZONE $AUTH_NAMESERVER | tail -1 | cut -d\ -f7)
if [ -z "$AUTH_SOA_SERIAL" ]; then
NAGIOS_STATE=CRITICAL
NAGIOS_RESULT=2
NAGIOS_DETAILS="$NAGIOS_DETAILS$n$DNS_ZONE: unknown domain (unable to resolve)"
else
NAMESERVER_OK=
NAMESERVER_HIGHER=
NAMESERVER_LOWER=
NAMESERVER_EMPTY=
NAMESERVERS=$DNS_SERVERS
if [ -z "$DNS_SERVERS" -o "$DNS_SERVER_LOOKUP" == '-n' -o "$DNS_SERVERS" == "$AUTH_NAMESERVER" ]; then
NAMESERVERS="$NAMESERVERS $(host -t ns $DNS_ZONE $AUTH_NAMESERVER | fgrep -v : | sed "s/.* //;s/\.$//")"
fi
NAMESERVERS=$(echo $NAMESERVERS | tr ' ' '\n' | sort -u)
for NAMESERVER in $NAMESERVERS; do
if [ "$NAMESERVER" != "$AUTH_NAMESERVER" ]; then
SOA_SERIAL=$(host -t soa $DNS_ZONE $NAMESERVER | tail -1 | cut -d\ -f 7)
if [ -z "$SOA_SERIAL" ]; then
NAMESERVER_EMPTY="$NAMESERVER_EMPTY$NAMESERVER,"
elif [ "$SOA_SERIAL" -lt "$AUTH_SOA_SERIAL" ]; then
NAMESERVER_LOWER="$NAMESERVER_LOWER$NAMESERVER,"
elif [ "$SOA_SERIAL" -gt "$AUTH_SOA_SERIAL" ]; then
NAMESERVER_HIGHER="$NAMESERVER_HIGHER$NAMESERVER,"
else
NAMESERVER_OK="$NAMESERVER_OK$NAMESERVER,"
fi
fi
done
NAGIOS_DETAILS="$NAGIOS_DETAILS$n$DNS_ZONE: $AUTH_NAMESERVER($AUTH_SOA_SERIAL)"
[ -n "$NAMESERVER_OK" ] && NAGIOS_DETAILS="$NAGIOS_DETAILS ok:$NAMESERVER_OK"
[ -n "$NAMESERVER_HIGHER" ] && NAGIOS_DETAILS="$NAGIOS_DETAILS higher:$NAMESERVER_HIGHER"
[ -n "$NAMESERVER_LOWER" ] && NAGIOS_DETAILS="$NAGIOS_DETAILS lower:$NAMESERVER_LOWER"
[ -n "$NAMESERVER_EMPTY" ] && NAGIOS_DETAILS="$NAGIOS_DETAILS error:$NAMESERVER_EMPTY"
if [ -n "$NAMESERVER_HIGHER$NAMESERVER_LOWER$NAMESERVER_EMPTY" ]; then
NAGIOS_STATE=CRITICAL
NAGIOS_RESULT=2
fi
NAGIOS_DETAILS="${NAGIOS_DETAILS%,}"
fi
done
echo "DNSREPLICATION: $NAGIOS_STATE$NAGIOS_DETAILS"
exit $NAGIOS_RESULT

View File

@@ -1,11 +1,11 @@
#! /usr/bin/env python #! /usr/bin/env python3
# #
# check_otp - Nagios check plugin for LinOTP/PrivacyIDEA OTP validation # check_otp - Nagios check plugin for LinOTP/PrivacyIDEA OTP validation
# #
# Version 1.1, latest version, documentation and bugtracker available at: # Version 1.2, latest version, documentation and bugtracker available at:
# https://gitlab.lindenaar.net/scripts/nagios-plugins # https://gitlab.lindenaar.net/scripts/nagios-plugins
# #
# Copyright (c) 2018 Frederik Lindenaar # Copyright (c) 2018 - 2024 Frederik Lindenaar
# #
# This script is free software: you can redistribute and/or modify it under the # This script is free software: you can redistribute and/or modify it under the
# terms of version 3 of the GNU General Public License as published by the Free # terms of version 3 of the GNU General Public License as published by the Free
@@ -23,8 +23,8 @@ from time import time
from struct import pack from struct import pack
from hashlib import sha1 from hashlib import sha1
from getpass import getpass from getpass import getpass
from urllib import urlencode from urllib.parse import urlencode
from urllib2 import Request, HTTPError, URLError, urlopen from urllib.request import Request, HTTPError, URLError, urlopen
from ssl import CertificateError, \ from ssl import CertificateError, \
create_default_context as create_default_SSL_context, \ create_default_context as create_default_SSL_context, \
_create_unverified_context as create_unverified_SSL_context _create_unverified_context as create_unverified_SSL_context
@@ -33,7 +33,7 @@ from argparse import ArgumentParser as StandardArgumentParser, FileType, \
_StoreAction as StoreAction, _StoreConstAction as StoreConstAction _StoreAction as StoreAction, _StoreConstAction as StoreConstAction
# Constants (no need to change but allows for easy customization) # Constants (no need to change but allows for easy customization)
VERSION="1.1" VERSION="1.2"
PROG_NAME=os.path.splitext(os.path.basename(__file__))[0] PROG_NAME=os.path.splitext(os.path.basename(__file__))[0]
PROG_VERSION=PROG_NAME + ' ' + VERSION PROG_VERSION=PROG_NAME + ' ' + VERSION
HTTP_AGENT=PROG_NAME + '/' + VERSION HTTP_AGENT=PROG_NAME + '/' + VERSION
@@ -404,7 +404,7 @@ def nagios_exit(status, message, data=None):
if isinstance(v,list) else v) for k,v in data ]) if isinstance(v,list) else v) for k,v in data ])
else: else:
perfdata = '' perfdata = ''
print 'OTP %s: %s%s' % (status[0], message, perfdata) print('OTP %s: %s%s' % (status[0], message, perfdata))
sys.exit(status[1]) sys.exit(status[1])
@@ -412,9 +412,9 @@ if __name__ == '__main__':
try: try:
args = parse_args() args = parse_args()
except ArgumentParserError as e: except ArgumentParserError as e:
nagios_exit(NAGIOS_UNKNOWN,'error with setup: ' + e.message) nagios_exit(NAGIOS_UNKNOWN,'error with setup: ' + ','.join(e.args))
except (KeyboardInterrupt, EOFError) as e: except (KeyboardInterrupt, EOFError) as e:
print print()
nagios_exit(NAGIOS_UNKNOWN,'initialization aborted') nagios_exit(NAGIOS_UNKNOWN,'initialization aborted')
message = args.func.__name__ + ' authentication' message = args.func.__name__ + ' authentication'

View File

@@ -1,11 +1,11 @@
#! /usr/bin/env python #! /usr/bin/env python3
# #
# check_temperature - Nagios temperature check for DS18B20 sensor on RaspberryPi # check_temperature - Nagios temperature check for RaspberryPi-connected sensors
# #
# Version 1.2, latest version, documentation and bugtracker available at: # Version 1.3 latest version, documentation and bugtracker available at:
# https://gitlab.lindenaar.net/scripts/nagios-plugins # https://gitlab.lindenaar.net/scripts/nagios-plugins
# #
# Copyright (c) 2017 - 2019 Frederik Lindenaar # Copyright (c) 2017 - 2024 Frederik Lindenaar
# #
# This script is free software: you can redistribute and/or modify it under the # This script is free software: you can redistribute and/or modify it under the
# terms of version 3 of the GNU General Public License as published by the Free # terms of version 3 of the GNU General Public License as published by the Free
@@ -27,16 +27,37 @@ from argparse import ArgumentParser as StandardArgumentParser, FileType, \
import logging import logging
# Constants (no need to change but allows for easy customization) # Constants (no need to change but allows for easy customization)
VERSION="1.2" VERSION="1.3"
PROG_NAME=splitext(basename(__file__))[0] PROG_NAME=splitext(basename(__file__))[0]
PROG_VERSION=PROG_NAME + ' ' + VERSION PROG_VERSION=PROG_NAME + ' ' + VERSION
CPU_SENSOR_DEV = '/sys/class/thermal/thermal_zone0/temp' CPU_SENSOR_DEV = '/sys/class/thermal/thermal_zone0/temp'
CPU_SENSOR_SCALE=1000
I2C_BMX280_DEFAULT_ADDR=0x77
I2C_BMX280_CALIBRATE_ADDR=0x88
I2C_BMX280_CALIBRATE_LEN=24
I2C_BMX280_CAL_HUM0_ADDR=0xA1
I2C_BMX280_CAL_HUM_ADDR=0xE1
I2C_BMX280_CAL_HUM_LEN=7
I2C_BMX280_CONFIG_ADDR=0xF5
I2C_BMX280_CONFIG = 0xA0 # Stand_by time = 1000 ms
I2C_BMX280_CTRL_MEAS_ADDR=0xF4
I2C_BMX280_CTRL_MEAS=0x27 # Normal mode, Pressure
# and Temperature Oversampling rate = 1
I2C_BMX280_CTRL_HUM_ADDR=0xF2
I2C_BMX280_CTRL_HUM=1 # Humidity Oversampling rate = 1
I2C_BMX280_MEAS_ADDR=0xF7
I2C_BMX280_MEAS_LEN=8
I2C_BMX280_SENSOR_SCALE=5120.0
I2C_MCP9808_DEFAULT_ADDR=0x18
I2C_MCP9808_CONFIG_ADDR=0x1 I2C_MCP9808_CONFIG_ADDR=0x1
I2C_MCP9808_CONFIG = [ 0x00, 0x00 ] # continuous conversion (power-up default) I2C_MCP9808_CONFIG = [ 0x00, 0x00 ] # continuous conversion (power-up default)
I2C_MCP9808_PRECISION_ADDR=0x08 I2C_MCP9808_PRECISION_ADDR=0x08
I2C_MCP9808_PRECISION=3 # 0=0.5, 1=0.25, 2=0.125, 3=0.0625 degr. C I2C_MCP9808_PRECISION=3 # 0=0.5, 1=0.25, 2=0.125, 3=0.0625 degr. C
I2C_MCP9808_TEMP_ADDR=0x05 I2C_MCP9808_TEMP_ADDR=0x05
I2C_MCP9808_SENSOR_SCALE=16
W1_SENSOR_DEV_DIR = '/sys/bus/w1/devices/' W1_SENSOR_DEV_DIR = '/sys/bus/w1/devices/'
W1_SENSOR_DEV_PREFIX = '28-' W1_SENSOR_DEV_PREFIX = '28-'
W1_SENSOR_DEV_SUFFIX = '/w1_slave' W1_SENSOR_DEV_SUFFIX = '/w1_slave'
@@ -87,6 +108,11 @@ class SetLogFile(StoreAction):
############################################################################### ###############################################################################
def hex_int(string):
"""Use int()'s auto-detection to parse 10-base and 16-base (0x..) numbers"""
return int(string, 0);
def convert_celcius(temp_read, scale = 1): def convert_celcius(temp_read, scale = 1):
"""Converts raw temperature sensore value to degrees Celcius""" """Converts raw temperature sensore value to degrees Celcius"""
return float(temp_read) / float(scale) return float(temp_read) / float(scale)
@@ -99,32 +125,22 @@ def convert_farenheit(temp_read, scale = 1):
CONVERT_FARENHEIT = ( convert_farenheit, 'F', 'Farenheit' ) CONVERT_FARENHEIT = ( convert_farenheit, 'F', 'Farenheit' )
def isempty(string): ####################[ Get CPU temperature of Raspberry Pi ]####################
"""Checks whether string 'str' provided is unset or empty"""
return string is None or len(string) == 0
def hex_int(string):
"""Use int()'s auto-detection to parse 10-base and 16-base (0x..) numbers"""
return int(string, 0);
def read_rpi_cpu_temp(args): def read_rpi_cpu_temp(args):
"""Reads CPU temperature and converts it to desired unit, returns temperature""" """Reads CPU temperature ands returns it converted to desired unit"""
with open(args.file, 'r') as f: with open(args.file, 'r') as f:
lines = f.readlines() lines = f.readlines()
logger.debug('Temperature sensor data read from %s: %s', f.name, lines) logger.debug('Temperature sensor data read from %s: %s', f.name, lines)
temp_read = int(lines[0]) temp_read = int(lines[0])
temp = args.converter[0](temp_read) temp = args.converter[0](temp_read, CPU_SENSOR_SCALE)
logger.debug('Temperature sensor value %d is %.2f%s', temp_read, logger.debug('Temperature sensor value %d is %.2f%s', temp_read,
temp, args.converter[1]) temp, args.converter[1])
return temp, 1 return temp, 1
def read_i2c_mcp9808_temp(args): ###############[ Get I2C (sm)bus object and I2C device address ]###############
"""Returns temperature from I2C MCP9808 sensor in desired unit""" def i2c_get_smbus_devaddr(args):
try: try:
import smbus import smbus
except ImportError: except ImportError:
@@ -132,47 +148,166 @@ def read_i2c_mcp9808_temp(args):
import smbus2 as smbus import smbus2 as smbus
except ImportError: except ImportError:
logger.critical("Unable to import either smbus or smbus2 library"); logger.critical("Unable to import either smbus or smbus2 library");
raise ImportError("missing I2C library, please install python-smbus or smbus2"); raise ImportError("missing I2C library, please install smbus2 "
"or Debian python-smbus package ");
try: try:
bus = smbus.SMBus(args.i2cbus) # Get I2C bus return (smbus.SMBus(args.i2cbus), # get i2c bus
args.default_address if args.address is None else args.address)
except OSError as e: except OSError as e:
logger.critical(e) logger.critical(e)
raise IOError("Invalid I2C bus: %d" % args.i2cbus) raise IOError("Invalid I2C bus: %d" % args.i2cbus)
####################[ Get I2C BME280/BMP280 Sensor values ]####################
# Inspired by https://github.com/ControlEverythingCommunity/BME280
def read_i2c_bmX280(args):
"""Returns temperature from I2C BME280/BMP280 sensor in desired unit"""
i2c_bus, i2c_addr = i2c_get_smbus_devaddr(args)
def convertLE16(data, offset, signed=False):
result = (data[offset + 1] << 8) | data[offset]
if signed and result > 32767:
result -= 65536
return result
try: try:
bus.write_i2c_block_data(args.address, I2C_MCP9808_CONFIG_ADDR, # Get Temperature and Pressure Calibration Data
data = i2c_bus.read_i2c_block_data(i2c_addr, I2C_BMX280_CALIBRATE_ADDR,
I2C_BMX280_CALIBRATE_LEN)
dig_T1 = convertLE16(data, 0)
dig_T2 = convertLE16(data, 2, True)
dig_T3 = convertLE16(data, 4, True)
dig_P1 = convertLE16(data, 6)
dig_P2 = convertLE16(data, 8, True)
dig_P3 = convertLE16(data, 10, True)
dig_P4 = convertLE16(data, 12, True)
dig_P5 = convertLE16(data, 14, True)
dig_P6 = convertLE16(data, 16, True)
dig_P7 = convertLE16(data, 18, True)
dig_P8 = convertLE16(data, 20, True)
dig_P9 = convertLE16(data, 22, True)
if args.read_humidity:
# Get Humidity Calibration Data
dig_H1 = i2c_bus.read_byte_data(i2c_addr,I2C_BMX280_CAL_HUM0_ADDR)
data = i2c_bus.read_i2c_block_data(i2c_addr,I2C_BMX280_CAL_HUM_ADDR,
I2C_BMX280_CAL_HUM_LEN)
dig_H2 = convertLE16(data, 0, True)
dig_H3 = data[2]
dig_H4 = (data[3] << 4) | (data[4] & 0x0f)
dig_H5 = (data[5] << 4) | (data[4] >> 4)
dig_H6 = data[6]
if dig_H6 > 127:
dig_H6 -= 256
i2c_bus.write_byte_data(i2c_addr, I2C_BMX280_CTRL_HUM_ADDR,
I2C_BMX280_CTRL_HUM)
# Setup BMP280/BME280 configuration and wait 0.5 seconds for things to settle
i2c_bus.write_byte_data(i2c_addr, I2C_BMX280_CTRL_MEAS_ADDR,
I2C_BMX280_CTRL_MEAS)
i2c_bus.write_byte_data(i2c_addr, I2C_BMX280_CONFIG_ADDR,
I2C_BMX280_CONFIG)
sleep(0.5)
# Read sensor data and and convert using calibration data
data = i2c_bus.read_i2c_block_data(i2c_addr, I2C_BMX280_MEAS_ADDR,
I2C_BMX280_MEAS_LEN)
# Convert 20-bits Temperature and calculate value with calibration data
adc_t = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)
var1 = ((adc_t) / 16384.0 - (dig_T1) / 1024.0) * (dig_T2)
var2 = (((adc_t) / 131072.0 - (dig_T1) / 8192.0) * ((adc_t)/131072.0 - (dig_T1)/8192.0)) * (dig_T3)
t_fine = (var1 + var2)
# Convert 20-bits Pressure and calculate value with calibration data
adc_p = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
var1 = (t_fine / 2.0) - 64000.0
var2 = var1 * var1 * (dig_P6) / 32768.0
var2 = var2 + var1 * (dig_P5) * 2.0
var2 = (var2 / 4.0) + ((dig_P4) * 65536.0)
var1 = ((dig_P3) * var1 * var1 / 524288.0 + ( dig_P2) * var1) / 524288.0
var1 = (1.0 + var1 / 32768.0) * (dig_P1)
p = 1048576.0 - adc_p
p = (p - (var2 / 4096.0)) * 6250.0 / var1
var1 = (dig_P9) * p * p / 2147483648.0
var2 = p * (dig_P8) / 32768.0
pressure = (p + (var1 + var2 + (dig_P7)) / 16.0) / 100
extra_readings = [ ('pressure', pressure, 'hPa'), ]
if args.read_humidity:
# Convert 16-byte Humidity and calculate value with calibration data
adc_h = (data[6] << 8) | data[7]
var_H = ((t_fine) - 76800.0)
var_H = (adc_h - (dig_H4 * 64.0 + dig_H5 / 16384.0 * var_H)) * (dig_H2 / 65536.0 * (1.0 + dig_H6 / 67108864.0 * var_H * (1.0 + dig_H3 / 67108864.0 * var_H)))
humidity = var_H * (1.0 - dig_H1 * var_H / 524288.0)
if humidity > 100.0 :
humidity = 100.0
elif humidity < 0.0 :
humidity = 0.0
extra_readings += ('humidity', humidity, '%', 0, 100),
logger.debug('BME280 sensor data: temperature %#02x: %#x = %d, '
'pressure: %#x, humidity: %#x', i2c_addr, adc_t,
t_fine, adc_p, adc_h)
logger.debug('Sensor Humidity value is %.2f %%', humidity)
else:
logger.debug('BMP280 sensor data: temperature %#02x: %#x = %d, '
'pressure: %#x',i2c_addr, adc_t, t_fine, adc_p)
# convert temperature to right units and scale and return value
temp = args.converter[0](t_fine, I2C_BMX280_SENSOR_SCALE)
logger.debug('Sensor Temperature value %d is %.2f%s',
t_fine, temp, args.converter[1])
logger.debug('Sensor Pressure value is %.2f hPa', pressure)
return (temp, extra_readings), 1
except IOError as e:
logger.critical(e)
raise IOError("Error while communicating with I2C device %#02x" %
i2c_addr)
########################[ Get I2C MCP9808 Temperature ]########################
# Inspired by https://github.com/ControlEverythingCommunity/MCP9808
def read_i2c_mcp9808(args):
"""Returns temperature from I2C mcp9808 sensor in desired unit"""
i2c_bus, i2c_addr = i2c_get_smbus_devaddr(args)
try:
# Setup MCP9808 configuration and wait 0.5 seconds for things to settle
i2c_bus.write_i2c_block_data(i2c_addr, I2C_MCP9808_CONFIG_ADDR,
I2C_MCP9808_CONFIG) I2C_MCP9808_CONFIG)
bus.write_byte_data(args.address, I2C_MCP9808_PRECISION_ADDR, i2c_bus.write_byte_data(i2c_addr, I2C_MCP9808_PRECISION_ADDR,
I2C_MCP9808_PRECISION) I2C_MCP9808_PRECISION)
sleep(0.5) sleep(0.5)
# Read temperature (0x05), 2 bytes (MSB, LSB) # Read temperature (2 bytes - MSB,LSB) and convert to 13-bit signed int
data = bus.read_i2c_block_data(args.address, I2C_MCP9808_TEMP_ADDR, 2) data = i2c_bus.read_i2c_block_data(i2c_addr,I2C_MCP9808_TEMP_ADDR,2)
logger.debug('Temperature sensor data from MCP9808 %#02x: 0x%02x%02x', temp_read = ((data[0] & 0xF) << 8) | data[1]
args.address, data[0], data[1]) if (data[0] & 0x10):
temp_read = -temp_read
logger.debug('MCP9808 sensor data %#02x: 0x%02x%02x = %d',
i2c_addr, data[0], data[1], temp_read)
# Convert the data to 13-bits # convert temperatur to right units and scale and return value
temp_read = ((data[0] & 0x1F) * 256) + data[1] temp = args.converter[0](temp_read, I2C_MCP9808_SENSOR_SCALE)
if temp_read > 4095 :
temp_read -= 8192
temp = args.converter[0](temp_read, 16)
logger.debug('Temperature sensor value %d is %.2f%s', logger.debug('Temperature sensor value %d is %.2f%s',
temp_read, temp, args.converter[1]) temp_read, temp, args.converter[1])
return temp, 1 return temp, 1
except IOError as e: except IOError as e:
logger.critical(e) logger.critical(e)
raise IOError("Error while communicating with I2C device %#02x" % raise IOError("Error while communicating with I2C device %#02x" %
args.address) i2c_addr)
#####################[ Get 1-Wire sensor device filename ]#####################
def get_w1_sensor_device_filename(args, dev_dir=W1_SENSOR_DEV_DIR, def get_w1_sensor_device_filename(args, dev_dir=W1_SENSOR_DEV_DIR,
prefix=W1_SENSOR_DEV_PREFIX, suffix=W1_SENSOR_DEV_SUFFIX): prefix=W1_SENSOR_DEV_PREFIX, suffix=W1_SENSOR_DEV_SUFFIX):
"""Auto-determine sensor datafile name (unless args.file is set)""" """Auto-determine sensor datafile name (unless args.file is set)"""
if isempty(args.file): if not args.file:
search_pat = dev_dir + ('/' if dev_dir[-1]!='/' else '') search_pat = dev_dir + ('/' if dev_dir[-1]!='/' else '')
search_pat+= prefix + '*' if isempty(args.serial) else '*' + args.serial search_pat+= prefix + ('*' + args.serial if args.serial else '*')
logger.debug('looking for sensors with search pattern %s', search_pat) logger.debug('looking for sensors with search pattern %s', search_pat)
device_folders = glob(search_pat) device_folders = glob(search_pat)
@@ -194,7 +329,8 @@ def get_w1_sensor_device_filename(args, dev_dir=W1_SENSOR_DEV_DIR,
return filename return filename
def read_w1_ds18b20_temp(args): ###################[ Get 1-Wire DS18b20 sensor temperature ]###################
def read_w1_ds18b20(args):
"""Returns temperature from 1-wire ds18b20 sensor in desired unit""" """Returns temperature from 1-wire ds18b20 sensor in desired unit"""
device_file = get_w1_sensor_device_filename(args) device_file = get_w1_sensor_device_filename(args)
lines=[ '' ] lines=[ '' ]
@@ -225,6 +361,7 @@ def read_w1_ds18b20_temp(args):
raise ValueError(errmsg) raise ValueError(errmsg)
#######################[ Parse Command Line parameters ]#######################
def parse_args(): def parse_args():
"""Parse command line and get parameters from environment, if present""" """Parse command line and get parameters from environment, if present"""
@@ -260,7 +397,7 @@ def parse_args():
parser.add_argument('-l', '--logfile', action=SetLogFile, parser.add_argument('-l', '--logfile', action=SetLogFile,
help='send logging output to logfile') help='send logging output to logfile')
subparser = parser.add_subparsers(title='Supported temperature sensors') subparser = parser.add_subparsers(title='Supported temperature sensors', required=True)
cpuparser = ArgumentParser(add_help=False) cpuparser = ArgumentParser(add_help=False)
cpuparser.add_argument('-f', '--file', default=CPU_SENSOR_DEV, cpuparser.add_argument('-f', '--file', default=CPU_SENSOR_DEV,
@@ -275,10 +412,27 @@ def parse_args():
help='I2C Address of sensor, use 0x.. for hex (*)') help='I2C Address of sensor, use 0x.. for hex (*)')
i2cparser.add_argument('-b', '--i2cbus', default=1, type=int, i2cparser.add_argument('-b', '--i2cbus', default=1, type=int,
help='I2C Bus to use (defaults to 1)') help='I2C Bus to use (defaults to 1)')
cmdparser = subparser.add_parser('i2c_bme280', parents=[i2cparser],
help='read I2C connected BME280 sensor',
epilog='(*) default I2C address for an BME280 is %#x' %
I2C_BMX280_DEFAULT_ADDR)
cmdparser.set_defaults(func=read_i2c_bmX280, cmdparser=cmdparser, retries=0,
read_humidity=True, default_address=I2C_BMX280_DEFAULT_ADDR)
cmdparser = subparser.add_parser('i2c_bmp280', parents=[i2cparser],
help='read I2C connected BMP280 sensor',
epilog='(*) default I2C address for an BMP280 is %#x' %
I2C_BMX280_DEFAULT_ADDR)
cmdparser.set_defaults(func=read_i2c_bmX280, cmdparser=cmdparser, retries=0,
read_humidity=False, default_address=I2C_BMX280_DEFAULT_ADDR)
cmdparser = subparser.add_parser('i2c_mcp9808', parents=[i2cparser], cmdparser = subparser.add_parser('i2c_mcp9808', parents=[i2cparser],
help='read I2C connected MCP9808 sensor', help='read I2C connected MCP9808 sensor',
epilog='(*) default I2C address for an MCP9808 is 0x18') epilog='(*) default I2C address for an MCP9808 is %#x' %
cmdparser.set_defaults(func=read_i2c_mcp9808_temp, cmdparser=cmdparser, retries=0, address=0x18) I2C_MCP9808_DEFAULT_ADDR)
cmdparser.set_defaults(func=read_i2c_mcp9808, cmdparser=cmdparser,
retries=0, default_address=I2C_MCP9808_DEFAULT_ADDR)
w1parser = ArgumentParser(add_help=False) w1parser = ArgumentParser(add_help=False)
pgroup = w1parser.add_mutually_exclusive_group(required=False) pgroup = w1parser.add_mutually_exclusive_group(required=False)
@@ -286,7 +440,8 @@ def parse_args():
help='(unique part of) temperature sensor serial (*)') help='(unique part of) temperature sensor serial (*)')
pgroup.add_argument('-f', '--file', pgroup.add_argument('-f', '--file',
help='input file (or device) to obtain data from (*)') help='input file (or device) to obtain data from (*)')
w1parser.add_argument('-r', '--retries', type=int,default=W1_SENSOR_READ_RETRIES, w1parser.add_argument('-r', '--retries', type=int,
default=W1_SENSOR_READ_RETRIES,
help='number of times to retry reading sensor data when' help='number of times to retry reading sensor data when'
' unstable (defaults to %d)' % W1_SENSOR_READ_RETRIES) ' unstable (defaults to %d)' % W1_SENSOR_READ_RETRIES)
cmdparser = subparser.add_parser('w1_ds18b20', parents=[w1parser], cmdparser = subparser.add_parser('w1_ds18b20', parents=[w1parser],
@@ -295,7 +450,7 @@ def parse_args():
'matches %s* in %s, if multiple entries are found -s or -f must ' 'matches %s* in %s, if multiple entries are found -s or -f must '
'be used to specify which sensor to read.' % 'be used to specify which sensor to read.' %
(W1_SENSOR_DEV_PREFIX, W1_SENSOR_DEV_DIR)) (W1_SENSOR_DEV_PREFIX, W1_SENSOR_DEV_DIR))
cmdparser.set_defaults(func=read_w1_ds18b20_temp, cmdparser=cmdparser) cmdparser.set_defaults(func=read_w1_ds18b20, cmdparser=cmdparser)
# parse arguments and post-process command line options # parse arguments and post-process command line options
args = parser.parse_args() args = parser.parse_args()
@@ -304,6 +459,7 @@ def parse_args():
return args return args
############################[ Exit the Nagios way ]############################
def nagios_exit(status, message, data=None): def nagios_exit(status, message, data=None):
"""exit 'nagios-style', print status and message followed by perf. data""" """exit 'nagios-style', print status and message followed by perf. data"""
if logger.isEnabledFor(logging.CRITICAL): if logger.isEnabledFor(logging.CRITICAL):
@@ -313,17 +469,18 @@ def nagios_exit(status, message, data=None):
if isinstance(v,list) else v) for k,v in data ]) if isinstance(v,list) else v) for k,v in data ])
else: else:
perfdata = '' perfdata = ''
print 'Temperature %s: %s%s' % (status[0], message, perfdata) print('Temperature %s: %s%s' % (status[0], message, perfdata))
exit(status[1]) exit(status[1])
#################################[ Main logic ]#################################
if __name__ == '__main__': if __name__ == '__main__':
try: try:
args = parse_args() args = parse_args()
except ArgumentParserError as e: except ArgumentParserError as e:
nagios_exit(NAGIOS_UNKNOWN,'error with setup: ' + e.message) nagios_exit(NAGIOS_UNKNOWN,'error with setup: ' + ','.join(e.args))
except (KeyboardInterrupt, EOFError) as e: except (KeyboardInterrupt, EOFError) as e:
print print()
nagios_exit(NAGIOS_UNKNOWN,'initialization aborted') nagios_exit(NAGIOS_UNKNOWN,'initialization aborted')
try: try:
@@ -331,11 +488,16 @@ if __name__ == '__main__':
temperature, tries = args.func(args) temperature, tries = args.func(args)
endtime = time() endtime = time()
if isinstance(temperature, tuple):
temperature, extra_data = temperature
else:
extra_data = ()
except (KeyboardInterrupt) as e: except (KeyboardInterrupt) as e:
nagios_exit(NAGIOS_UNKNOWN,'temperature sensor read aborted by user') nagios_exit(NAGIOS_UNKNOWN,'sensor read aborted by user')
except (IOError, ValueError, ImportError) as e: except (IOError, ValueError, ImportError) as e:
nagios_exit(NAGIOS_UNKNOWN,'temperature sensor read failed: %s' % e) nagios_exit(NAGIOS_UNKNOWN,'sensor read failed: %s' % e)
elapse = endtime-starttime elapse = endtime-starttime
logger.info('Got temperature reading of %.2f degrees %s in %fs', logger.info('Got temperature reading of %.2f degrees %s in %fs',
@@ -343,6 +505,10 @@ if __name__ == '__main__':
unit = args.converter[1] unit = args.converter[1]
message = 'current temperature is %.2f%s' % (temperature, unit) message = 'current temperature is %.2f%s' % (temperature, unit)
data = [ ('temperature', [ '%f%s' % (temperature, unit),
args.warn, args.critical, None, None]),
('retries', [ tries-1, None, args.retries, 0, None ]),
('checktime', [ '%fs' % elapse, None, None, 0, None]) ]
if args.critical is not None and temperature > args.critical: if args.critical is not None and temperature > args.critical:
nagiosresult = NAGIOS_CRITICAL nagiosresult = NAGIOS_CRITICAL
message+= ' and exceeds critical threshold %.2f%s' %(args.critical,unit) message+= ' and exceeds critical threshold %.2f%s' %(args.critical,unit)
@@ -352,10 +518,10 @@ if __name__ == '__main__':
else: else:
nagiosresult = NAGIOS_OK nagiosresult = NAGIOS_OK
nagios_exit(nagiosresult, message, [ for e in extra_data:
('temperature', [ '%f%s' % (temperature, unit), message += ', %s is %.2f%s' % (e[0], e[1], e[2])
args.warn, args.critical, None, None]), data += (e[0], [ '%f%s' % (e[1], e[2]), None, None,
('retries', [ tries-1, None, args.retries, 0, None ]), e[3] if len(e)>3 else None, e[4] if len(e)>4 else None ]),
('checktime', [ '%fs' % elapse, None, None, 0, None])
]) nagios_exit(nagiosresult, message, data)