#!/bin/bash # ====================================================================== # # Check RAM usage # # requirements: # - bc # # DOC: https://access.redhat.com/solutions/406773 # explains /proc/meminfo # # SYNTAX: # check_memory [-w [int] -c [int] -s [int]] # -w Warning level for RAM usage [%]; default: 75 # -c Critical level for RAM usage; default: 90 # -s Critical level for SWAP usage; default: 5 # # ---------------------------------------------------------------------- # 2020-03-16 v1.0 <axel.hahn@iml.unibe.ch> # 2020-03-25 v1.1 <axel.hahn@iml.unibe.ch> added slab; fix usage based on MemAvailable # 2020-04-28 v1.2 <axel.hahn@iml.unibe.ch> allow small swap usage before critical; update output RAM + Swap usage # 2020-07-08 v1.3 <axel.hahn@iml.unibe.ch> FIX: set "ph." instead "ps." # 2020-07-16 v1.4 <axel.hahn@iml.unibe.ch> FIX: add unit MB in the performance data (see #3939) # 2021-03-24 v1.5 <axel.hahn@iml.unibe.ch> increase Swap critical limit 5 --> 50 # 2022-03-09 v1.6 <axel.hahn@iml.unibe.ch> show most ram intensive processes # 2022-03-10 v1.7 <axel.hahn@iml.unibe.ch> add cli param -p; update help # 2023-02-13 v1.8 <axel.hahn@unibe.ch> shell fixes # 2023-07-28 v1.9 <axel.hahn@unibe.ch> update help page # 2023-09-14 v1.10 <axel.hahn@unibe.ch> fix sort: write failed: 'standard output': Broken pipe # ====================================================================== . "$(dirname $0)/inc_pluginfunctions" self_APPVERSION=1.10 # ---------------------------------------------------------------------- # FUNCTIONS # ---------------------------------------------------------------------- # get a memory status value # /proc/meminfo conatains values in kB - it is divided by 1024 # --> return values are MB function getMemvalue(){ echo $( grep "^$1:" /proc/meminfo | awk '{ print $2 }' ) / 1024 | bc } # show help text function showHelp(){ local _self; _self=$(basename $0) cat <<EOF $( ph.showImlHelpHeader ) Check memory usage incl. free, used and total memory. On higher memory usage the process table with top 5 top consumers will be shown. This plugin sends performancedata. SYNTAX: $(basename $0) [-w WARN_LIMIT] [-c CRITICAL_LIMIT] [-s SWAP_LIMIT] [-p PROCESS_LIMIT] [-h] OPTIONS: -w VALUE Warning level for RAM usage [%]; default: 75 -c VALUE Critical level for RAM usage; default: 90 -s VALUE Critical level for SWAP usage; default: 50 -p VALUE show process info with highest memory consumption if usage is > NN %; default: 50 -h or --help show this help. PARAMETERS: none EXAMPLE: $(basename $0) -w 90 -c 95 -p 70 EOF } # ---------------------------------------------------------------------- # MAIN # ---------------------------------------------------------------------- case "$1" in "--help"|"-h") showHelp exit 0 ;; *) esac # --- check required tools ph.require bc # ---------------------------------------------------------------------- # set default / override from command line params typeset -i iWarnLimit; iWarnLimit=$( ph.getValueWithParam 75 w "$@") typeset -i iCriticalLimit; iCriticalLimit=$( ph.getValueWithParam 90 c "$@") typeset -i iCriticalSwap; iCriticalSwap=$( ph.getValueWithParam 50 s "$@") typeset -i iMinRamUsageToShowProcesses; iMinRamUsageToShowProcesses=$( ph.getValueWithParam 50 p "$@") # ---------------------------------------------------------------------- # read values # --- RAM typeset -i ramTotal; ramTotal=$( getMemvalue MemTotal) typeset -i ramAvail; ramAvail=$( getMemvalue MemAvailable) typeset -i ramUsed; ramUsed=$ramTotal-$ramAvail typeset -i ramFree; ramFree=$( getMemvalue MemFree) typeset -i ramBuffers; ramBuffers=$( getMemvalue Buffers) typeset -i ramCached; ramCached=$( getMemvalue Cached) typeset -i ramSReclaim; ramSReclaim=$( getMemvalue SReclaimable) typeset -i ramUsage; ramUsage=$(echo "($ramUsed) *100 / $ramTotal " | bc) # --- Swap typeset -i swapTotal; swapTotal=$( getMemvalue SwapTotal) typeset -i swapFree; swapFree=$( getMemvalue SwapFree) typeset -i swapCached; swapCached=$( getMemvalue SwapCached) typeset -i swapUsage=0 if [ $swapTotal -gt 0 ]; then swapUsage=$(echo "($swapCached)*100 / $swapTotal " | bc) fi # ---------------------------------------------------------------------- # set status ph.setStatusByLimit $ramUsage $iWarnLimit $iCriticalLimit # if [ $swapCached -gt 0 ]; then if [ $swapUsage -ge $iCriticalSwap ]; then ph.setStatus "critical" fi if [ $swapTotal -gt 0 ]; then ph.status "RAM usage $ramUsage % of $ramTotal MB .. SWAP usage $swapCached MB = $swapUsage % of $swapTotal MB total" else ph.status "RAM usage $ramUsage % of $ramTotal MB (machine has no Swap)" fi # ---------------------------------------------------------------------- # output # --- show details echo grep -E "^(Mem|Cache|Buffers|Swap|Slab|SReclaimable)" "/proc/meminfo" # v1.6: show most consuming processes if usage is > nn % if [ $ramUsage -gt $iMinRamUsageToShowProcesses ]; then echo echo "RAM usage is higher $iMinRamUsageToShowProcesses percent ... showing most consuming processes:" ps aux | head -1 # sort: write failed: 'standard output': Broken pipe # ps aux | sort -nrk 4 | head -n 5 ps aux | sort -nrk 4 | sed -n "1,5p" fi # --- performance data ph.perfadd "memory-total" "${ramTotal}MB" "" "" 0 ${ramTotal} ph.perfadd "memory-used" "${ramUsed}MB" "" "" 0 ${ramTotal} ph.perfadd "memory-avail" "${ramAvail}MB" "" "" 0 ${ramTotal} ph.perfadd "memory-free" "${ramFree}MB" "" "" 0 ${ramTotal} ph.perfadd "memory-buffers" "${ramBuffers}MB" "" "" 0 ${ramTotal} ph.perfadd "memory-cached" "${ramCached}MB" "" "" 0 ${ramTotal} ph.perfadd "memory-sreclaim" "${ramSReclaim}MB" "" "" 0 ${ramTotal} # add swap performance data only if swap is available if [ $swapTotal -gt 0 ]; then ph.perfadd "swap-total" "${swapTotal}MB" "" "" 0 ${swapTotal} ph.perfadd "swap-free" "${swapFree}MB" "" "" 0 ${swapTotal} ph.perfadd "swap-cached" "${swapCached}MB" "" "" 0 ${swapTotal} fi ph.exit # ----------------------------------------------------------------------