commit
974f052a77
@ -0,0 +1,77 @@ |
||||
## About |
||||
|
||||
**Bash APC scripts** - other method for APC AP96xx than apcupsd or nut. |
||||
|
||||
*I express my gratitude to [Alexey Maksimov](https://blog.it-kb.ru/about-this-blog/) for examples of working snmp handlers - (fork of [his code](https://github.com/Aleksey-Maksimov/check_snmp_apc_ups_state) is in the attachment)* |
||||
|
||||
### This apc_snmp_metrics.sh script can show current state from networked APC UPS. |
||||
|
||||
Tested on **Centos 7 GNU/Linux** with **AP9618** in **SURTD3000XLI**, with external termistor **AP9512TBLK** |
||||
|
||||
<br/> |
||||
|
||||
## Usage |
||||
To start you need: |
||||
1. add IP (string number 14 variable IPS) |
||||
2. add the user (string number 15 variable SUSER) |
||||
3. add the bot token (string number 20 variable TOKEN) |
||||
4. add chat ID (string number 21 variable CHAT_ID) |
||||
5. add the directory (optional - defalts creates in ```$(pwd)``` dir) |
||||
6. create an init file (optional, see the example **apcups_telegram.service** file) |
||||
|
||||
#### For one-shot (non-interactive) - simple run in bash: |
||||
|
||||
``` |
||||
~# bash apc_snmp_metrics.sh |
||||
``` |
||||
And there is example of success result (database not created, only verbosed hypothetic name with path) : |
||||
|
||||
``` |
||||
DB 2023.1112.0043_apc-metric.db |
||||
WATTS 16 |
||||
AMPRS 2 |
||||
CBATT 17 |
||||
CEEXT 22 |
||||
INPWA 221 |
||||
PRBAT 100 |
||||
REMAT 1:15:05.00 |
||||
BAREP 1 |
||||
DATES 1699739034 |
||||
DATEN 491653013 |
||||
EXITS 0 |
||||
``` |
||||
|
||||
**WATTS** - percent of UPS load in watts |
||||
**AMPRS** - current load in amperes |
||||
**CBATT** - internal battery temperature |
||||
**CEEXT** - external AP9512TBLK temperature |
||||
**INPWA** - input line voltage |
||||
**PRBAT** - percent of charge batteries |
||||
**REMAT** - remain time for current load if 220/230 line turns off |
||||
**BAREP** - battery replasing key - 1 is OK, 2 is REPLACE |
||||
**DATES** - unix-seconds (date) of local machine |
||||
**DATEN** - nano-seconds, each string need for being unique |
||||
**EXITS** - exit-code from snmpget utility, used in Telegram function |
||||
|
||||
<br/> |
||||
|
||||
### For daemonized use ```--run``` argument (mode for systemd unit) |
||||
|
||||
#### This mode creates sqlite database file, than you can get logged data from it. |
||||
The database is created anew every time you start it, create a separate directory within /usr/share/ for example. |
||||
``` |
||||
$ bash apc_snmp_metrics.sh --run |
||||
DB /root/2023.1112.0043_apc-metric.db |
||||
``` |
||||
### Warning! Monitor the disk usage, this script cat write more than 2 MB of data per hour! |
||||
|
||||
#### For reading sqlite database (daemonized data-log) - run |
||||
|
||||
```~# bash apc_read_sql_strings.sh``` |
||||
This script searching for last writed .db file in specified folder and SELECTing from |
||||
|
||||
<br/> |
||||
|
||||
### Also have fun! Bash rules! |
||||
|
||||
 |
After Width: | Height: | Size: 55 KiB |
@ -0,0 +1,18 @@ |
||||
#!/bin/bash |
||||
|
||||
cd # write directory for sqlitedb file |
||||
DATABASE=$( ls -t *_apc-metric.db | head -1 ) |
||||
du -sh $DATABASE |
||||
|
||||
sqlreadtable(){ |
||||
cat << FEO | sqlite3 $DATABASE |
||||
.timeout 2000 |
||||
SELECT * FROM ( \ |
||||
SELECT * FROM mainmetric0 \ |
||||
ORDER BY id DESC LIMIT 10 )\ |
||||
ORDER BY id ; |
||||
FEO |
||||
} |
||||
|
||||
sqlreadtable |
||||
|
@ -0,0 +1,109 @@ |
||||
#!/bin/bash |
||||
|
||||
OIDS=$( cat << EOF |
||||
1.3.6.1.4.1.318.1.1.1.4.2.3.0 |
||||
1.3.6.1.4.1.318.1.1.1.4.2.4.0 |
||||
1.3.6.1.4.1.318.1.1.1.2.2.2.0 |
||||
1.3.6.1.4.1.318.1.1.10.2.3.2.1.4.1 |
||||
1.3.6.1.4.1.318.1.1.1.3.2.1.0 |
||||
1.3.6.1.4.1.318.1.1.1.2.2.1.0 |
||||
1.3.6.1.4.1.318.1.1.1.2.2.3.0 |
||||
1.3.6.1.4.1.318.1.1.1.7.2.3.0 |
||||
EOF |
||||
) |
||||
IPS='' # add ip of APC AP module |
||||
SUSER='' # add snmp user (version 3) |
||||
cd # write directory for sqlitedb file |
||||
|
||||
funcsend(){ |
||||
if [[ "$EXITS" != "0" ]]; then |
||||
TOKEN="" # write Telegrambot token |
||||
CHAT_ID="" # write Telegram chat id |
||||
curl -s -X POST \ |
||||
https://api.telegram.org/bot"$TOKEN"/sendMessage \ |
||||
-d chat_id="$CHAT_ID" \ |
||||
-d text="ERROR IN APC SNMPGET" |
||||
sleep 10 |
||||
fi |
||||
} |
||||
|
||||
funconexit(){ |
||||
exit 0 |
||||
} |
||||
trap 'funconexit' SIGINT |
||||
|
||||
DATABASE="$(date "+%Y.%m%d.%H%M")_apc-metric.db" |
||||
echo DB "$DATABASE" |
||||
|
||||
sqlcreatetables(){ |
||||
cat << EFO | sqlite3 "$DATABASE" |
||||
.timeout 200 |
||||
CREATE TABLE IF NOT EXISTS mainmetric0 \ |
||||
( id INTEGER PRIMARY KEY AUTOINCREMENT, \ |
||||
watts TEXT, amperes TEXT, battemp TEXT, \ |
||||
exttemp TEXT, input TEXT, battperc TEXT, \ |
||||
remainperc TEXT, replace TEXT, unixsec TEXT, \ |
||||
msec TEXT, exitcodes TEXT ); |
||||
EFO |
||||
} |
||||
|
||||
sqlwritetable(){ |
||||
sqlcreatetables |
||||
cat << EOF | sqlite3 "$DATABASE" |
||||
.timeout 200 |
||||
INSERT INTO mainmetric0 ( watts, amperes, battemp, \ |
||||
exttemp, input, battperc, remainperc, replace, \ |
||||
unixsec, msec, exitcodes ) \ |
||||
VALUES ( "$WATTS", "$AMPRS", \ |
||||
"$CBATT", "$CEEXT", "$INPWA", \ |
||||
"$PRBAT", "$REMAT", "$BAREP", \ |
||||
"$DATES", "$DATEN", "$EXITS" ); |
||||
EOF |
||||
} |
||||
|
||||
funcrun(){ |
||||
VARS="$( snmpget -u $SUSER -v 3 $IPS $OIDS 2>/dev/null )" |
||||
EXITS="$?" |
||||
# Percentage load (of watts) |
||||
WATTS=$( echo "$VARS" | grep '4.2.3.0' | grep -o '[^ ]*$' ) |
||||
# Amperes of load |
||||
AMPRS=$( echo "$VARS" | grep '4.2.4.0' | grep -o '[^ ]*$' ) |
||||
# Celsius on battery |
||||
CBATT=$( echo "$VARS" | grep '2.2.2.0' | grep -o '[^ ]*$' ) |
||||
# External celsius |
||||
CEEXT=$( echo "$VARS" | grep '2.1.4.1' | grep -o '[^ ]*$' ) |
||||
# Volts input |
||||
INPWA=$( echo "$VARS" | grep '3.2.1.0' | grep -o '[^ ]*$' ) |
||||
# battery percents |
||||
PRBAT=$( echo "$VARS" | grep '2.2.1.0' | grep -o '[^ ]*$' ) |
||||
# remaining time |
||||
REMAT=$( echo "$VARS" | grep '2.2.3.0' | grep -o '[^ ]*$' ) |
||||
# battery replace (replace if =2) |
||||
BAREP=$( echo "$VARS" | grep '7.2.3.0' | grep -o '[^ ]*$' ) |
||||
# datetimer |
||||
DATES=$( date "+%s" ) |
||||
DATEN=$( date "+%N" ) |
||||
} |
||||
|
||||
RUNANSW01=$( echo "$@" | grep -oP '\--run' | grep -oP 'run' ) |
||||
if [[ "$RUNANSW01" = "run" ]]; then |
||||
while : ; do |
||||
funcrun &>/dev/null |
||||
sqlwritetable |
||||
funcsend &>/dev/null |
||||
done |
||||
else |
||||
funcrun &>/dev/null |
||||
funcsend &>/dev/null |
||||
echo WATTS $WATTS |
||||
echo AMPRS $AMPRS |
||||
echo CBATT $CBATT |
||||
echo CEEXT $CEEXT |
||||
echo INPWA $INPWA |
||||
echo PRBAT $PRBAT |
||||
echo REMAT $REMAT |
||||
echo BAREP $BAREP |
||||
echo DATES $DATES |
||||
echo DATEN $DATEN |
||||
echo EXITS $EXITS |
||||
fi |
@ -0,0 +1,16 @@ |
||||
|
||||
[Unit] |
||||
Description=APC SNMP TRIGGER |
||||
Requires=network-online.target |
||||
|
||||
[Service] |
||||
Type=simple |
||||
User=root |
||||
Group=root |
||||
ExecStart=/bin/bash /root/apcups_telegram.sh |
||||
Restart=always |
||||
RestartSec=10 |
||||
TimeoutSec=10 |
||||
|
||||
[Install] |
||||
WantedBy=multi-user.target |
@ -0,0 +1,32 @@ |
||||
#!/bin/bash |
||||
|
||||
IPS='' # add ip of APC AP module |
||||
SUSER1='' # add snmp user |
||||
|
||||
funcsnmp(){ |
||||
cd check_snmp_apc_ups_state |
||||
bash check_snmp_apc_ups_state.sh -H $IPS -P 1 -C $SUSER1 |
||||
} |
||||
|
||||
funcsend(){ |
||||
TOKEN="" # write Telegrambot token |
||||
CHAT_ID="" # write Telegram chat id |
||||
curl -s -X POST \ |
||||
https://api.telegram.org/bot"$TOKEN"/sendMessage \ |
||||
-d chat_id="$CHAT_ID" \ |
||||
-d text="$varfuncsnmp" |
||||
} |
||||
|
||||
varf=$( funcsnmp | md5sum ) |
||||
while :; do |
||||
sleep 1 |
||||
varfuncsnmp="$( funcsnmp )" |
||||
vars=$( echo "$varfuncsnmp" | md5sum ) |
||||
|
||||
if [[ $vars != $varf ]]; then |
||||
# echo EDITED $(date "+%F_%s") |
||||
funcsend > /dev/null |
||||
fi |
||||
varf=$vars |
||||
# sleep 5 |
||||
done |
@ -0,0 +1,44 @@ |
||||
## About |
||||
### this is [fork of original](https://github.com/Aleksey-Maksimov/check_snmp_apc_ups_state) by Alexey Maximov |
||||
### |
||||
|
||||
**check_snmp_apc_ups_state** - Icinga Plugin Script (Check Command). |
||||
|
||||
It calculate APC UPS current state from SNMP data in upsBasicStateOutputState |
||||
|
||||
Tested on **Debian GNU/Linux 9.11 (Stretch)** with **Icinga r2.10.5-1** |
||||
|
||||
Put here: /usr/lib/nagios/plugins/check_snmp_apc_ups_state.sh |
||||
|
||||
PreReq: **snpmget** tool |
||||
|
||||
## Usage |
||||
|
||||
Options: |
||||
|
||||
``` |
||||
$ /usr/lib/nagios/plugins/check_snmp_apc_ups_state.sh [OPTIONS] |
||||
|
||||
Option GNU long option Meaning |
||||
------ -------------- ------- |
||||
-H --hostname Host name, IP Address |
||||
-P --protocol SNMP protocol version. Possible values: 1|2c|3 |
||||
-C --community SNMPv1/2c community string for SNMP communication (for example,public) |
||||
-L --seclevel SNMPv3 securityLevel. Possible values: noAuthNoPriv|authNoPriv|authPriv |
||||
-a --authproto SNMPv3 auth proto. Possible values: MD5|SHA |
||||
-x --privproto SNMPv3 priv proto. Possible values: DES|AES |
||||
-U --secname SNMPv3 username |
||||
-A --authpassword SNMPv3 authentication password |
||||
-X --privpasswd SNMPv3 privacy password |
||||
-q --help Show this message |
||||
-v --version Print version information and exit |
||||
|
||||
``` |
||||
Example for all UPS types: |
||||
|
||||
``` |
||||
$ ./check_snmp_apc_ups_state.sh -H ups001.holding.com -P 2c -C public |
||||
``` |
||||
Icinga Director integration manual (in Russian): |
||||
|
||||
[Icinga плагин check_snmp_apc_ups_state для расширенного отслеживания аварийных состояний ИБП APC по данным, полученным по протоколу SNMP из параметра upsBasicStateOutputState](https://blog.it-kb.ru/2019/09/20/icinga-plugin-check_snmp_apc_ups_state-for-abnormal-conditions-monitoring-of-apc-ups-from-snmp-in-flags-from-upsbasicstateoutputstate/) |
@ -0,0 +1,199 @@ |
||||
#!/bin/bash |
||||
# |
||||
# Icinga Plugin Script (Check Command). It calculate APC UPS current state from SNMP data in upsBasicStateOutputState |
||||
# Aleksey Maksimov <aleksey.maksimov@it-kb.ru> |
||||
# Tested on Debian GNU/Linux 9.11 (Stretch) with Icinga r2.10.5-1 |
||||
# Put here: /usr/lib/nagios/plugins/check_snmp_apc_ups_state.sh |
||||
# Usage example: |
||||
# ./check_snmp_apc_ups_state.sh -H ups-nmc-01.holding.com -P 2c -C public |
||||
# |
||||
PLUGIN_NAME="Icinga Plugin Check Command to calculate APC UPS current state (from SNMP data)" |
||||
PLUGIN_VERSION="2019.09.16" |
||||
PRINTINFO=`printf "\n%s, version %s\n \n" "$PLUGIN_NAME" "$PLUGIN_VERSION"` |
||||
# |
||||
# Exit codes |
||||
# |
||||
codeOK=0 |
||||
codeWARNING=1 |
||||
codeCRITICAL=2 |
||||
codeUNKNOWN=3 |
||||
# |
||||
# OID |
||||
# |
||||
checkOID="1.3.6.1.4.1.318.1.1.1.11.1.1.0" |
||||
# |
||||
Usage() { |
||||
echo "$PRINTINFO" |
||||
echo "Usage: $0 [OPTIONS] |
||||
|
||||
Option GNU long option Meaning |
||||
------ --------------- ------- |
||||
-H --hostname Host name, IP Address |
||||
-P --protocol SNMP protocol version. Possible values: 1|2c|3 |
||||
-C --community SNMPv1/2c community string for SNMP communication (for example,"public") |
||||
-L --seclevel SNMPv3 securityLevel. Possible values: noAuthNoPriv|authNoPriv|authPriv |
||||
-a --authproto SNMPv3 auth proto. Possible values: MD5|SHA |
||||
-x --privproto SNMPv3 priv proto. Possible values: DES|AES |
||||
-U --secname SNMPv3 username |
||||
-A --authpassword SNMPv3 authentication password |
||||
-X --privpasswd SNMPv3 privacy password |
||||
-q --help Show this message |
||||
-v --version Print version information and exit |
||||
|
||||
" |
||||
} |
||||
# |
||||
# Parse arguments |
||||
# |
||||
if [ -z $1 ]; then |
||||
Usage; exit $codeUNKNOWN; |
||||
fi |
||||
# |
||||
OPTS=`getopt -o H:P:C:L:a:x:U:A:X:qv -l hostname:,protocol:,community:,seclevel:,authproto:,privproto:,secname:,authpassword:,privpasswd:,help,version -- "$@"` |
||||
eval set -- "$OPTS" |
||||
while true; do |
||||
case $1 in |
||||
-H|--hostname) HOSTNAME=$2 ; shift 2 ;; |
||||
-P|--protocol) |
||||
case "$2" in |
||||
"1"|"2c"|"3") PROTOCOL=$2 ; shift 2 ;; |
||||
*) printf "Unknown value for option %s. Use '1' or '2c' or '3'\n" "$1" ; exit $codeUNKNOWN ;; |
||||
esac ;; |
||||
-C|--community) COMMUNITY=$2 ; shift 2 ;; |
||||
-L|--seclevel) |
||||
case "$2" in |
||||
"noAuthNoPriv"|"authNoPriv"|"authPriv") v3SECLEVEL=$2 ; shift 2 ;; |
||||
*) printf "Unknown value for option %s. Use 'noAuthNoPriv' or 'authNoPriv' or 'authPriv'\n" "$1" ; exit $codeUNKNOWN ;; |
||||
esac ;; |
||||
-a|--authproto) |
||||
case "$2" in |
||||
"MD5"|"SHA") v3AUTHPROTO=$2 ; shift 2 ;; |
||||
*) printf "Unknown value for option %s. Use 'MD5' or 'SHA'\n" "$1" ; exit $codeUNKNOWN ;; |
||||
esac ;; |
||||
-x|--privproto) |
||||
case "$2" in |
||||
"DES"|"AES") v3PRIVPROTO=$2 ; shift 2 ;; |
||||
*) printf "Unknown value for option %s. Use 'DES' or 'AES'\n" "$1" ; exit $codeUNKNOWN ;; |
||||
esac ;; |
||||
-U|--secname) v3SECNAME=$2 ; shift 2 ;; |
||||
-A|--authpassword) v3AUTHPWD=$2 ; shift 2 ;; |
||||
-X|--privpasswd) v3PRIVPWD=$2 ; shift 2 ;; |
||||
-q|--help) Usage ; exit $codeOK ;; |
||||
-v|--version) echo "$PRINTINFO" ; exit $codeOK ;; |
||||
--) shift ; break ;; |
||||
*) Usage ; exit $codeUNKNOWN ;; |
||||
esac |
||||
done |
||||
# |
||||
# Set SNMP connection paramaters |
||||
# |
||||
vCS=$( echo " -O qvn -v $PROTOCOL" ) |
||||
if [ "$PROTOCOL" = "1" ] || [ "$PROTOCOL" = "2c" ] |
||||
then |
||||
vCS=$vCS$( echo " -c $COMMUNITY" ); |
||||
elif [ "$PROTOCOL" = "3" ] |
||||
then |
||||
vCS=$vCS$( echo " -l $v3SECLEVEL" ); |
||||
vCS=$vCS$( echo " -a $v3AUTHPROTO" ); |
||||
vCS=$vCS$( echo " -x $v3PRIVPROTO" ); |
||||
vCS=$vCS$( echo " -A $v3AUTHPWD" ); |
||||
vCS=$vCS$( echo " -X $v3PRIVPWD" ); |
||||
vCS=$vCS$( echo " -u $v3SECNAME" ); |
||||
fi |
||||
# |
||||
# Calculate APC UPS State |
||||
# |
||||
vOIDOut=$( snmpget $vCS $HOSTNAME $checkOID ) |
||||
vOIDOut=$( echo $vOIDOut | tr -d '"' ) |
||||
if [ ${#vOIDOut} -ne 64 ]; then |
||||
echo "The string length obtained from the SNMP parameter 'upsBasicStateOutputState' is not equal to 64 characters. So we cannot parse the data." |
||||
exit $codeUNKNOWN |
||||
fi |
||||
|
||||
declare -a vFlags=( |
||||
"Flag 01: Abnormal Condition Present" |
||||
"Flag 02: On Battery" |
||||
"Flag 03: Low Battery" |
||||
"Flag 04: On Line" |
||||
"Flag 05: Replace Battery" |
||||
"Flag 06: Serial Communication Established" |
||||
"Flag 07: AVR Boost Active" |
||||
"Flag 08: AVR Trim Active" |
||||
"Flag 09: Overload" |
||||
"Flag 10: Runtime Calibration" |
||||
"Flag 11: Batteries Discharged" |
||||
"Flag 12: Manual Bypass" |
||||
"Flag 13: Software Bypass" |
||||
"Flag 14: In Bypass due to Internal Fault" |
||||
"Flag 15: In Bypass due to Supply Failure" |
||||
"Flag 16: In Bypass due to Fan Failure" |
||||
"Flag 17: Sleeping on a Timer" |
||||
"Flag 18: Sleeping until Utility Power Returns" |
||||
"Flag 19: On" |
||||
"Flag 20: Rebooting" |
||||
"Flag 21: Battery Communication Lost" |
||||
"Flag 22: Graceful Shutdown Initiated" |
||||
"Flag 23: Smart Boost or Smart Trim Fault" |
||||
"Flag 24: Bad Output Voltage" |
||||
"Flag 25: Battery Charger Failure" |
||||
"Flag 26: High Battery Temperature" |
||||
"Flag 27: Warning Battery Temperature" |
||||
"Flag 28: Critical Battery Temperature" |
||||
"Flag 29: Self Test In Progress" |
||||
"Flag 30: Low Battery / On Battery" |
||||
"Flag 31: Graceful Shutdown Issued by Upstream Device" |
||||
"Flag 32: Graceful Shutdown Issued by Downstream Device" |
||||
"Flag 33: No Batteries Attached" |
||||
"Flag 34: Synchronized Command is in Progress" |
||||
"Flag 35: Synchronized Sleeping Command is in Progress" |
||||
"Flag 36: Synchronized Rebooting Command is in Progress" |
||||
"Flag 37: Inverter DC Imbalance" |
||||
"Flag 38: Transfer Relay Failure" |
||||
"Flag 39: Shutdown or Unable to Transfer" |
||||
"Flag 40: Low Battery Shutdown" |
||||
"Flag 41: Electronic Unit Fan Failure" |
||||
"Flag 42: Main Relay Failure" |
||||
"Flag 43: Bypass Relay Failure" |
||||
"Flag 44: Temporary Bypass" |
||||
"Flag 45: High Internal Temperature" |
||||
"Flag 46: Battery Temperature Sensor Fault" |
||||
"Flag 47: Input Out of Range for Bypass" |
||||
"Flag 48: DC Bus Overvoltage" |
||||
"Flag 49: PFC Failure" |
||||
"Flag 50: Critical Hardware Fault" |
||||
"Flag 51: Green Mode/ECO Mode" |
||||
"Flag 52: Hot Standby" |
||||
"Flag 53: Emergency Power Off (EPO) Activated" |
||||
"Flag 54: Load Alarm Violation" |
||||
"Flag 55: Bypass Phase Fault" |
||||
"Flag 56: UPS Internal Communication Failure" |
||||
"Flag 57: Efficiency Booster Mode" |
||||
"Flag 58: Off" |
||||
"Flag 59: Standby" |
||||
"Flag 60: Minor or Environment Alarm") |
||||
|
||||
|
||||
vFlag1=$( echo $vOIDOut | awk '{print substr($0,0,1)}' ) |
||||
|
||||
vFlagsStr="" |
||||
vIndex=0 |
||||
for vFlag in "${vFlags[@]}"; do |
||||
|
||||
vFlagN=$( echo ${vOIDOut:vIndex:1} ) |
||||
if [ "$vFlagN" -eq "1" ]; then |
||||
vFlagsStr=$vFlagsStr$( echo "\n${vFlag}" ); |
||||
fi |
||||
let vIndex=${vIndex}+1 |
||||
done |
||||
|
||||
# |
||||
# Icinga Check Plugin output |
||||
# |
||||
if [ "$vFlag1" -eq "1" ]; then |
||||
echo -e "APC UPS State CRITICAL \nCurrent active flags:$vFlagsStr" |
||||
exit $codeCRITICAL |
||||
elif [ "$vFlag1" -eq "0" ]; then |
||||
echo -e "APC UPS State OK \nCurrent active flags:$vFlagsStr" |
||||
exit $codeOK |
||||
fi |
||||
exit $codeUNKNOWN |
Loading…
Reference in new issue