# NRPE script for monitoring load average

This script converts a server load value into percentage, compares it with non desired state ($warning and$critical) and returns all information in NRPE (Nagios Remote Plugin Executor) friendly output.

Desired output:

Goal: Use so much less external commands how is possible. Why? I would like to have the script independent. The second thing is just training purpose of bash scripting.

#!/usr/bin/env bash

set -o errexit -o pipefail

warning=95
critical=100

# 1. Find out a load was before 15 minutes.
# citation: "Frankly, if your box spikes above 1.0 on the one-minute average, you're still fine. It's when the 15-minute average goes north of 1.0 and stays there that you need to snap to."

# 2. Count all cores.
# citation: "How the cor es are spread out over CPUs doesn't matter. Two quad-cores == four dual-cores == eight single-cores. It's all eight cores for these purposes."
if [[ ${row[0]} = "cpu" ]] && [[${row[1]} = "cores" ]]; then
cpu_cores=$(( cpu_cores + "${row[3]}" ))
fi
done < /proc/cpuinfo

# 3. Convert load value into percentage.
# citation: "Sometimes it's helpful to consider load as percentage of the available resources (the load value divided by the number or cores).
# source: https://access.redhat.com/solutions/30554
load_mlt=$(echo "$quarter_load_average*100/1" | bc)
load_prc=$(( "$load_mlt" / "$cpu_cores" )) # 4. Compare result with desired status and prepare returned value. if [[ -z "$load_prc" ]]; then
returned_code=3
else
returned_text="CPU_CORES=$cpu_cores load=$quarter_load_average | load_in_percent=$load_prc;$warning;$critical" if [[$load_prc -gt $critical ]]; then returned_code=2 elif [[$load_prc -gt $warning ]]; then returned_code=1 else returned_code=0 fi fi echo "$returned_text"
exit $returned_code  • Welcome to Code Review. I have rolled back your edit. Please do not update the code in your question to incorporate feedback from answers, doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers. – Heslacher Aug 15 '19 at 13:20 ## 3 Answers This looks pretty good. Some suggestions: 1. [[ is preferred over [ in Bash. 2. This script could benefit from set -o errexit -o nounset -o pipefail. You'll need to set cpu_cores=0 before referring to it in the loop, but that's just best practice. 3. Dividing by one isn't going to do much :) 4. The quotes are a cute feature, but I'd much rather see a summary of the point in them than the full sentences. Something like Treat 15 minute load average above 1 as critical. A useful tactic I've found when dealing with comments is to think how you could name things to avoid comments altogether. Code can't lie, and names are very much like comments enshrined in code, so if you for example rename minute15 to quarter_load_average or something else human readable you should be able to remove the 1. Find out a load was before 15 minutes. comment above it. 5. Since you're only interested in one row from /proc/cpuinfo I would grep for it. Your goal of making the script stand-alone should be weighed against at least • maintainability, which will suffer greatly if you only use builtin commands, • speed, which is already not great for read, and • availability of grep, which is pretty much universal by now. 6. You can redirect a line to standard input using some_command <<< "$line" to avoid redundant echos. So echo "$quarter_load_average*100/1" | bc could instead be bc <<< "$quarter_load_average*100/1".
• 3. Well, there is a purpose. Maybe is there a better way of that. :) $echo 0.5*100 | bc = 50.0 $ echo 0.5*100/1 | bc = 50. – David Mosler Aug 15 '19 at 12:05

I’d agree with all of l0b0’s answer – including the suggestion of using grep to process /proc/cpuinfo. An alternate way to count all CPU cores using an AWK one-liner would be:

cpu_cores=$(awk '/cpu cores/ { num_cores +=$4} END { print num_cores}' /proc/cpuinfo)


This would also remove the usage of Bash arrays, resulting in the script being POSIX-compatible – if that’s something you’re interested in. (dash performs better than bash for running scripts but any performance gain would be negated by the time it takes to run awk).

There are aritmetic syntax issues. Due to that it doesn't work under GNU bash, version 4.2.46(2)-release

cpu_cores=$(( cpu_cores + "${row[3]}" ))
load_prc=$(( "$load_mlt" / "$cpu_cores" ))  Should be: cpu_cores=$(( cpu_cores + row[3] ))