#!/bin/bash # ====================================================================== # # NAGIOS CLIENT CHECK :: haproxy status # show current requests to frontend and backend # # ---------------------------------------------------------------------- # settings values are parsed by a given section. # if it fails it scans other sections .. finally default and global # see getCfgvar # ---------------------------------------------------------------------- # 2020-04-27 v1.0 <axel.hahn@iml.unibe.ch> # 2020-04-28 v1.1 <axel.hahn@iml.unibe.ch> added status and max connections for frontend and backend # 2020-04-29 v1.2 <axel.hahn@iml.unibe.ch> parse ini section by given section # 2020-06-03 v1.3 <axel.hahn@iml.unibe.ch> added ping to each backend server # ====================================================================== . `dirname $0`/inc_pluginfunctions cfgfile=/etc/haproxy/haproxy.cfg cfgfile2=/tmp/haproxy.config tmpfile=/tmp/check_haproxy_status_$$ tmpfile2=/tmp/check_haproxy_status2_$$ tmpfileping=/tmp/check_haproxy_status3_$$ # ---------------------------------------------------------------------- # pre checks # ---------------------------------------------------------------------- ph.reqire wget if [ ! -f $cfgfile ]; then ph.abort "UNKNOWN: config file does not exist: $cfgfile" fi cat $cfgfile >/dev/null if [ $? -ne 0 ]; then ph.abort "UNKNOWN: unable to read ha proxy config $cfgfile ... `ls -l $cfgfile`" fi cat $cfgfile | grep "\ mode\ .*http" >/dev/null if [ $? -ne 0 ]; then ph.abort "UNKNOWN: haproxy is not in http mode" fi # ---------------------------------------------------------------------- # functions # ---------------------------------------------------------------------- # rewrite the ha proxy config file to parse it by section function cfgrewriter(){ local _section= IFS='' while read line do echo $line | grep "^[a-z]" >/dev/null if [ $? -eq 0 ]; then _section=$line echo "# new section: $_section" fi echo $line | grep "^\ \ [a-z]*" >/dev/null if [ $? -eq 0 ]; then echo -n "$_section: " echo $line | sed "s#\ \ # #g" fi done < $cfgfile } # get a value from a given a given section function _getCfgVarFromSection(){ local _var=$1 local _section=$2 grep "^${_section}:\ \ ${_var}\ " $cfgfile2 >/dev/null && ( typeset -i local _iColumnVal=`echo "${_section}: $_var" | wc -c`+1 grep "^${_section}:\ \ ${_var}\ " $cfgfile2 | cut -c ${_iColumnVal}- ) } # get a value from config - with autoscan of other sections function getCfgvar(){ local _var=$1 local _section=$2 _getCfgVarFromSection "${_var}" "${_section}" \ || _getCfgVarFromSection "${_var}" "frontend stats_frontend" \ || _getCfgVarFromSection "${_var}" "frontend couchdb_frontend" \ || _getCfgVarFromSection "${_var}" "frontend postgresql_frontend" \ || _getCfgVarFromSection "${_var}" "frontend opencpu" \ || _getCfgVarFromSection "${_var}" "frontend apache_fop" \ || _getCfgVarFromSection "${_var}" "defaults" \ || _getCfgVarFromSection "${_var}" "global" } # find a column number of a given field name in haproxy csv function getColnumber(){ cat $tmpfile | head -1 | sed 's#,#\n#g' | grep -n "^$1$" | cut -f 1 -d ':' } # get column #N function getColumn(){ typeset -i local _iNumber=$1 local _filter=$2 test -z $_filter && _filter='.*' grep "$_filter" $tmpfile | grep -v "stats_frontend" | cut -f 2,$_iNumber -d ',' } # ---------------------------------------------------------------------- # build url # ---------------------------------------------------------------------- cfgrewriter >$cfgfile2 # getCfgvar "bind" "frontend stats_frontend" # getCfgvar "stats auth" "frontend stats_frontend" # exit proto=http auth= host=localhost typeset -i port=80 uri= getCfgvar "bind" "frontend stats_frontend" | grep "\ ssl\ " >/dev/null && proto=https auth=`getCfgvar "stats auth" "frontend stats_frontend"` port=`getCfgvar "bind" "frontend stats_frontend" | cut -f 2 -d ':' | cut -f 1 -d " "` host=`getCfgvar "bind" "frontend stats_frontend" | cut -f 1 -d ':'` uri=` getCfgvar "stats uri" "frontend stats_frontend"` if [ "$host" = "*" ]; then host="localhost" fi url="$proto://${auth}@${host}:${port}${uri};csv;norefresh" urlmasked="$proto://*password*@${host}:${port}${uri};csv;norefresh" # ---------------------------------------------------------------------- # check output # ---------------------------------------------------------------------- # --- get status page wget --no-check-certificate -O $tmpfile $url 2>/dev/null if [ $? -ne 0 ]; then rm -f $tmpfile $cfgfile2 ph.abort "UNKNOWN: url $urlmasked did not respond. `wget --no-check-certificate -O - -S $url`" fi colLimit=`getColnumber "slim"` colCurrentConnections=`getColnumber "scur"` colStatus=`getColnumber "status"` statusFront=`getColumn $colStatus ",FRONTEND," | cut -f 2 -d ","` statusBack=` getColumn $colStatus ",BACKEND," | cut -f 2 -d ","` typeset -i iMaxConnFront=`getColumn $colLimit ",FRONTEND,"` typeset -i iMaxConnBack=` getColumn $colLimit ",BACKEND,"` typeset -i iFrontend=`getColumn $colCurrentConnections ",FRONTEND,"` typeset -i iFrontendFree=$iMaxConnFront-$iFrontend typeset -i iBackend=` getColumn $colCurrentConnections ",BACKEND," ` typeset -i iBackendFree=$iMaxConnBack-$iBackend statusExt= if [ ! "$statusFront" = "OPEN" ]; then ph.setStatus "critical" statusExt="${statusExt}ERROR: frontend status is not OPEN - it is ${statusFront}\n" fi if [ ! "$statusBack" = "UP" ]; then ph.setStatus "critical" statusExt="${statusExt}ERROR: backend status is not UP - it is ${statusBack}\n" fi ph.status "FRONT: $statusFront - ${iFrontend} (max: ${iMaxConnFront}) .. BACK: $statusBack - $iBackend (max: ${iMaxConnBack})" test -z "$statusExt" || echo "${statusExt}" # echo; echo DEBUG: ; cat $tmpfile ph.perfadd "frontend" "${iFrontend}" ph.perfadd "frontend-max" "${iMaxConnFront}" ph.perfadd "frontend-free" "${iFrontendFree}" ph.perfadd "backend" "${iBackend}" ph.perfadd "backend-max" "${iMaxConnBack}" ph.perfadd "backend-free" "${iBackendFree}" # ---------------------------------------------------------------------- # show server connections and summary (FRONTEND/ BACKEND) # ---------------------------------------------------------------------- getColumn $colCurrentConnections | sed -n "2,$ p" >$tmpfile2 while read line do srv=`echo $line | cut -f 1 -d ","` val=`echo $line | cut -f 2 -d ","` label=`echo $srv | tr [:upper:] [:lower:]` # echo "${srv} - ${val}" echo -n "${srv} - ${val} " # v1.3: if it is a servername then ping to it echo ${srv} | grep "^[a-z0-9\-\.]" >/dev/null if [ $? -eq 0 ]; then ping -c 1 ${srv} >$tmpfileping grep "\ 0%\ packet\ loss" $tmpfileping >/dev/null if [ $? -eq 0 ]; then echo "- Ping OK" else echo "- Ping FAILED" cat $tmpfileping test "`ph.status`" = "OK" && ph.setStatus "warning" fi rm -f $tmpfileping else echo fi # performance data: send summary only # echo ${srv} | egrep "(FRONTEND|BACKEND)" >/dev/null && ph.perfadd "${label}" "${val}" done < $tmpfile2 rm -f $cfgfile2 $tmpfile $tmpfile2 2>/dev/null ph.exit # ----------------------------------------------------------------------