Last active
January 14, 2020 12:58
-
-
Save Decstasy/6a9c7c50cb965a77e5e4a1058f4e060b to your computer and use it in GitHub Desktop.
Icinga check to get network interface performance data
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Dennis Ullrich | |
# [email protected] | |
#################################### | |
############# Variables ########## | |
################################ | |
# Arrays | |
declare -A interface | |
declare -A stats | |
declare -A unit | |
declare -A unit_name | |
# Tmpfile | |
# WARNING: It will be redeclared while parsing the argument "-i"! | |
stats[tmpfile]="/tmp/check_net_if_stats.tmp" | |
# Units for calculation | |
unit[b]="1" | |
unit[k]="1000" | |
unit[m]="1000^2" | |
unit[g]="1000^3" | |
unit[t]="1000^4" | |
# Units for output | |
unit_name[b]="b" | |
unit_name[k]="k" | |
unit_name[m]="m" | |
unit_name[g]="g" | |
unit_name[t]="t" | |
#################################### | |
############# Functions ########## | |
################################ | |
usage() { | |
cat << EOF | |
Usage: ${0##*/} [-hd] [-i interface] [-u unit] | |
-h Display this help and exit | |
-d Debug mode (be aware - your terminal will be spammed) | |
-i [interface] e.g. eth0, lan0, bond0 etc... | |
-u [unit] b, k, m, g, t (bit/s (default), kbit/s, mbit/s, gbit/s, tbit/s) | |
-p [precision] Number of digits behind dot. Only 0-9 allowed. Default: 0 | |
EOF | |
exit 0 | |
} | |
interface_exists() { | |
if ! grep -qm1 "${interface[name]}:" /proc/net/dev; then | |
>&2 echo "CRITICAL: Interface \"${interface[name]}\" not found in /proc/net/dev!" | |
exit 2 | |
fi | |
} | |
read_stats() { | |
stats[new-timestamp]=`date "+%s"` | |
stats[new-data]=$(awk "/${interface[name]}/{print \$1,\$2,\$10}" /proc/net/dev) | |
newtmp=( ${stats[new-data]} ) | |
stats[old-timestamp]=$(stat -c %Y ${stats[tmpfile]}) | |
stats[old-data]="$(awk "/${interface[name]}/{print \$1,\$2,\$10}" ${stats[tmpfile]})" | |
oldtmp=( ${stats[old-data]} ) | |
stats[timestamp-diff]=$(( ${stats[new-timestamp]} - ${stats[old-timestamp]} )) | |
interface[rx-new]=${newtmp[1]} | |
interface[rx-old]=${oldtmp[1]} | |
interface[tx-new]=${newtmp[2]} | |
interface[tx-old]=${oldtmp[2]} | |
} | |
write_stats() { | |
cat /proc/net/dev > ${stats[tmpfile]} | |
} | |
detect_time_leap() { | |
if [ "${stats[timestamp-diff]}" -le 0 ]; then | |
>&2 echo "WARNING: Time leap detected! Stats written. Wait for next cycle. |rx_${interface[name]}=0.000${unit_name[${interface[unit]}]};;;;tx_${interface[name]}=0.000${unit_name[${interface[unit]}]};;;;" | |
exit 1 | |
fi | |
} | |
detect_if_reset() { | |
# if the new counter is smaller than the old counter, we have detected an interface reset | |
for x in rx tx; do | |
if [ "${interface[$x-new]}" -lt "${interface[$x-old]}" ]; then | |
>&2 echo "WARNING: Interface \"${interface[name]}\" has been resetted! Stats written. Wait for next cycle. |rx_${interface[name]}=0.000${unit_name[${interface[unit]}]};;;;tx_${interface[name]}=0.000${unit_name[${interface[unit]}]};;;;" | |
exit 1 | |
fi | |
done | |
} | |
calculate_stats() { | |
for x in rx tx; do | |
# scale for 0.xxx precision | |
# calculate difference between old and new rx * 8 to get it in bit, divide with timestamp diff since last run and divide to target unit | |
# check if result is between 0 and 1 and print a 0 since bc does not print a leading zero by default | |
interface[$x-sec]=$(bc <<< "scale=${unit[precision]} | |
result=(( ${interface[$x-new]} - ${interface[$x-old]} ) * 8 ) / ${stats[timestamp-diff]} / ${unit[${interface[unit]}]} | |
if (0 <= result && result < 1 && result != 0) { | |
print \"0\" | |
} | |
print result;") | |
done | |
} | |
############################################### | |
############# Parse, check, set... ########## | |
########################################### | |
# Parse args | |
while getopts “:hdi:u:p:” OPTION; do | |
case $OPTION in | |
d) # Debug | |
set -x | |
;; | |
h) usage | |
;; | |
i) interface[name]="$OPTARG" | |
stats[tmpfile]="/tmp/check_net_if_stats_${interface[name]}.tmp" | |
;; | |
u) if [[ ! "$OPTARG" =~ ^[bkmgt]$ ]]; then | |
>&2 echo "Unknown unit $OPTARG in Option $OPTION. Execute script with -h option to get help."; exit 3 | |
fi | |
interface[unit]="$OPTARG" | |
;; | |
p) if [[ ! "$OPTARG" =~ ^[0-9]$ ]]; then | |
>&2 echo "Scale \"$OPTARG\" is not between 0 and 9 in Option $OPTION. Execute script with -h option to get help."; exit 3 | |
fi | |
unit[precision]=$OPTARG | |
;; | |
'?') >&2 echo "Unknown argument $OPTARG in Option $OPTION. Execute script with -h option to get help."; exit 3 | |
;; | |
esac | |
done | |
# remove the options and optional -- | |
shift "$((OPTIND-1))" | |
# Set default(s) | |
[ -z ${interface[unit]} ] && interface[unit]="b" | |
[ -z ${unit[precision]} ] && unit[precision]=0 | |
# Check input | |
if [ -z ${interface[name]} ] || [ -z ${interface[unit]} ] || [ -z ${unit[precision]} ]; then | |
>&2 echo 'UNKNOWN: Not all required arguments are given. Execute script with -h option to get help.' | |
exit 3 | |
fi | |
############################### | |
############# MAIN ########## | |
########################### | |
if ! type bc > /dev/null 2>&1; then | |
echo "UNKNOWN: bc is not installed on this machine!" | |
exit 3 | |
fi | |
interface_exists | |
if [ ! -f "${stats[tmpfile]}" ]; then | |
write_stats | |
echo "OK: Stats written. Wait for next cycle." | |
exit 0 | |
fi | |
read_stats | |
write_stats | |
detect_time_leap | |
detect_if_reset | |
calculate_stats | |
# output if everything is fine | |
rx="'rx_${interface[name]}'=${interface[rx-sec]}${unit_name[${interface[unit]}]};0;0;0;0" | |
tx="'tx_${interface[name]}'=${interface[tx-sec]}${unit_name[${interface[unit]}]};0;0;0;0" | |
perfdata="${rx} ${tx}" | |
echo "OK: Interface ${interface[name]} RX: ${interface[rx-sec]} ${unit_name[${interface[unit]}]}/s, TX: ${interface[tx-sec]} ${unit_name[${interface[unit]}]}/s | ${perfdata}" | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment