1
\$\begingroup\$

This script based on previous NRPE script for monitoring load average. Same purpouse - get NRPE friendly output with minimal usage of non built in commands. In this case wasn't need to count with floating point. So I could omit bc.

Yes, I read Why is using a shell loop to process text considered bad practice. And there is a lot of true. Bud I am still thinking about these NRPE scripts as about bash scripting trainnig to get more practice.

Desired output:

MEMORY_TOTAL=2041316kB MEMORY_AVAILABLE=1049260kB | MEMORY_IN_PERCENTAGE=51;80;90

#!/usr/bin/env bash

set -o errexit -o pipefail

warning=80
critical=90


while read -a meminfo_row; do
  # Remove the colon character. 
  row_value_lenght=$(( ${#meminfo_row[0]} -1 ))
  row_value=${meminfo_row[0]:0:$row_value_lenght}

  case $row_value in
    MemTotal)
      mem_total=${meminfo_row[1]}
      mem_apercent=$(( meminfo_row[1] / 100 ))
    ;;
    MemAvailable)
      mem_available=${meminfo_row[1]}
    ;;
  esac
done < /proc/meminfo


mem_percentage=$(( mem_available / mem_apercent ))


if [[ -z $mem_percentage ]]; then
  returned_text="MEMORY UNKNOWN - check script"
  returned_code=3
else
  returned_text="MEMORY_TOTAL=${mem_total}kB MEMORY_AVAILABLE=${mem_available}kB | MEMORY_IN_PERCENTAGE=$mem_percentage;$warning;$critical"
  if [[ $mem_percentage -gt $critical ]]; then
    returned_code=2
  elif [[ $mem_percentage -gt $warning ]]; then
    returned_code=1
  else
    returned_code=0
  fi
fi

echo "$returned_text" 
exit $returned_code
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

I don't understand why it should be a warning to have over 80% of the system RAM available. If anything needs a warning, it should be having under 20% of RAM available, right?

Reading each line into an array is overcomplicated. The read builtin command is quite good at splitting each line of input into multiple variables. (row_value_lenght is misspelled, by the way.)

The proc(5) man page says about /proc/meminfo:

Each line of the file consists of a parameter name, followed by a colon, the value of the parameter, and an option unit of measurement (e.g., "kB").

There's no guarantee that the unit will be kB (as you have assumed in your printout), or that both lines of interest will have the same units.

Splitting up the calculation of mem_percentage is weird.

The echo statement should be line-wrapped for readability.

The cases for exit codes 0, 1 and 2 can be collapsed into one, using arithmetic.

#!/usr/bin/env bash

set -o errexit -o pipefail

warning=80
critical=90

while read -r label number unit ; do
    case "$label" in
      MemTotal:)
        mem_total=$number
        mem_total_unit=$unit
        ;;
      MemAvailable:)
        mem_avail=$number
        mem_avail_unit=$unit
        ;;
    esac
done < /proc/meminfo

if [ -z "$mem_avail" -o "$mem_avail_unit" != "$mem_total_unit" ]; then
    echo "MEMORY UNKNWOWN - check script"
    exit 3
fi

mem_avail_percent=$(( 100 * $mem_avail / $mem_total ))
echo "MEMORY_TOTAL=$mem_total$mem_total_unit" \
     "MEMORY_AVAILABLE=$mem_avail$mem_avail_unit" \
     "|" \
     "MEMORY_IN_PERCENTAGE=$mem_avail_percent;$warning;$critical"
exit $(( ($mem_avail_percent > $warning) + ($mem_avail_percent > $critical) ))
\$\endgroup\$
1
  • \$\begingroup\$ Thanks a lot for the great tips. I just turned aritmetic operation as: warning="20"; critical="10"; mem_avail_percent="5"; echo $(( $mem_avail_percent < $warning) + ($mem_avail_percent < $critical) )) = 2. I really like that. \$\endgroup\$ Aug 16, 2019 at 9:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.