Skip to content
Snippets Groups Projects
check_docker_stats 6.55 KiB
#!/bin/bash
# ======================================================================
#
# Check DOCKER INFOS
#
# requirements:
# - docker
# - sudo permissions on docker command
# - jq
# - bc
#
# ----------------------------------------------------------------------
# Cli docs:
# https://docs.docker.com/engine/reference/commandline/docker/
# ----------------------------------------------------------------------
# 2024-01-26  v1.0  <axel.hahn@unibe.ch>      init
# 2024-01-29  v1.1  <axel.hahn@unibe.ch>      fix help; detect reason for no output
# ======================================================================


. $(dirname $0)/inc_pluginfunctions
. $(dirname $0)/inc_dockerfunctions.sh

self_APPVERSION=1.1

# ----------------------------------------------------------------------
# FUNCTIONS
# ----------------------------------------------------------------------


# show help
function _showHelp(){
    local _self=$( basename $0 )
    cat <<EOH
$( ph.showImlHelpHeader )

Show resources of running docker instances.

This check provides performance data except on mode "all".

USAGE:
  $_self [OPTIONS]

OPTIONS:

  General:
  -h, --help        this help
  -d, --debug       Debug; Flag: show docker env values.

  Connect to docker:
  -p, --path        Custom directory for docker binary
  -t, --target      Custom docker target; value for DOCKER_HOST
                    Needed only if Docker does not run on a unix socket or
                    multiple users run a rootless docker daemon.

  mode:
  -m, --mode MODE   Mode what kind of information to show.
                    The output of container list is sorted by the maximum 
                    value first.

                      all       default; This view is unsorted.
                                This check has no performance data.

                      cpu       CPU usage total of all containers
                      mem       Memory max usage of most consuming container

                      memtotal  sum of memory usage
                      netio     sum of netio of all containers IN and OUT
                      blockio   sum of blockio of all containers IN and OUT

EXAMPLES:
  $_self
    Show stats of all containers

  $_self -p /usr/bin
    Show stats of all containers. The docker binary will be searched in
    given path first - then in all other dirs of \$PATH

  $_self -d
    Show stats of all containers and json with docker env infos.

  $_self -m cpu
    Show cpu usage total of all containers. The container list is sorted
    by cpu usage. The most consuming container is on top.

EOH
}

# ----------------------------------------------------------------------
# MAIN
# ----------------------------------------------------------------------

bOptDebug=0
sMode="all"
while [[ "$#" -gt 0 ]]; do case $1 in
    -h|--help)        _showHelp; exit 0;;
    -d|--debug)       bOptDebug=1; shift;;
    -p|--path)        PATH="$2:$PATH"; shift; shift;;
    -m|--mode)        sMode="$2"; shift; shift;;
    -t|--target)      export DOCKER_HOST="$2"; shift; shift;;
    *) echo "ERROR: Unknown parameter: $1"; _showHelp; exit 1;
esac; done

sLabel="Docker stats"

case "$sMode" in
  "cpu")      sLabel="Docker CPU usage total of all containers: %s percent";            sUnit="1"; sumkey="CPUPerc";        sColumns=".Container, .${sumkey}, .Name" ;;
  "mem")      sLabel="Docker Memory max usage in most consuming container: %s percent"; sUnit="1"; maxkey="MemPerc";        sColumns=".Container, .${maxkey}, .MemUsage, .Name" ;;
  "netio")    sLabel="Docker Network I/O of all containers: %s MB IN .. %s MB OUT";     sUnit="M"; sumkey="NetIO";    f2=1; sColumns=".Container, .${sumkey}, .Name" ;;
  "memtotal") sLabel="Docker Memory usage of all containers: %s MB";                    sUnit="M"; sumkey="MemUsage"; f2=0; sColumns=".Container, .${sumkey}, .Name" ;;
  "blockio")  sLabel="Docker Block I/O of all containers: %s MB IN .. %s MB OUT";       sUnit="M"; sumkey="BlockIO";  f2=1; sColumns=".Container, .${sumkey}, .Name" ;;
  "all") ;;
  *) ph.setStatus critical
     echo "ERROR: mode [$sMode] is unknown. Use -h to get help."
     ph.exit
esac

test -z "$sColumns" && sColumns=".Container, .CPUPerc, .MemUsage, .MemPerc, .NetIO, .PIDs, .Name"


ph.require "docker"
ph.require "jq"
ph.require "bc"

_detectDockerenv

# --- get stats data

data=$( sudo -n --preserve-env docker stats --no-stream --format '{{ json . }}' )
_detectDockererror "$data"


# --- checks to detect maximum

if [ -n "${maxkey}" ]; then
  iMax=0 
  sMax=$( echo "$data" | tr -d '%' | jq -r ".${maxkey}" | sort -hr | head -1 | sed "s#^\.#0#" )
  iMax=$( ph.toUnit "$sMax" "1" 0 )
  ph.perfadd "${sMode}-max" "$iMax" "" "" 0 "100"
  sLabel=$( printf "${sLabel}" ${sMax} )
fi


# --- checks with sum of a value

if [ -n "${sumkey}" ]; then
  sum=0
  # split 2 value field - get the 1st one. example: "81.1kB / 1.66MB" --> "81.1k"
  for myval in $( echo "$data" | tr -d '%' | jq -r ".${sumkey}" | cut -f 1 -d " " | tr -d "B" )
  do
    valuniq=$( ph.toUnit "$myval" "" )
    sum=$( bc <<< "$valuniq + ${sum}" )
  done
  test "$sUnit" = "1" && sumhr=$( ph.toUnit "$sum" "1" 0 )
  test "$sUnit" = "M" && sumhr=$( ph.toUnit "$sum" "M" 3 )

  # --- checks with IN and OUT

  if [ "$f2" = "1" ]; then
    sum2=0
    # split 2 value field - get the 2nd one. example: "81.1kB / 1.66MB" --> "1.66M"
    for myval in $( echo "$data" | tr -d '%' | jq -r ".${sumkey}" | cut -f 3 -d " " | tr -d "B" )
    do
      valuniq=$( ph.toUnit "$myval" "" )
      sum2=$( bc <<< "$valuniq + ${sum2}" )
    done
    ph.perfadd "${sMode}-1"  "$sum" "" ""
    ph.perfadd "${sMode}-2" "$sum2" "" ""
    sum2hr=$( ph.toUnit "$sum2" "M" 3 )

    sLabel=$( printf "${sLabel}" ${sumhr} ${sum2hr} )

  else
    ph.perfadd "${sMode}-sum" "$sum" "" ""
    sLabel=$( printf "${sLabel}" ${sumhr} )
  fi
fi


# --- output
line="------------------------------------------------------------------------------------------"

ph.status "$sLabel"

if [ "$sMode" = "all" ]; then
  echo "ID              CPU %   MEM USAGE / LIMIT       MEM %   NET I/O         PIDs    Name"
  echo "$line"
  jq -r "[$sColumns] | @tsv" <<< "$data"
fi

if [ -n "${maxkey}" ]; then
  echo "ID              ${maxkey}"
  echo "$line"
  jq -r "[$sColumns] | @tsv" <<< "$data" | sort -k +2 -h -r
fi

if [ -n "${sumkey}" ]; then
  echo "ID              ${sumkey}"
  echo "$line"
  jq -r "[$sColumns] | @tsv" <<< "$data" | sort -k +2 -h -r
fi

echo

# if -d was given then show debug infos too
test $bOptDebug -eq 1 && ( echo; echo "DEBUG: full docker system infos as json"; echo "$data" | jq ; _debugInfos)

ph.exit


# ----------------------------------------------------------------------