Skip to content
Snippets Groups Projects
check_dns_responsetime 4.28 KiB
#!/bin/bash
# ======================================================================
#
# Check DNS response time
# requirements:
# - netstat
#
# ----------------------------------------------------------------------
# 2020-06-17  v1.0  <axel.hahn@iml.unibe.ch>
# 2021-11-12  v1.1  <axel.hahn@iml.unibe.ch>  check fqd instead of fixed value
#                                             test tcp 53 first
#                                             check result depends on 1st nameserver only
# 2022-10-24  v1.2  <axel.hahn@unibe.ch>      shell fixes; remove pipe char in output
# 2023-07-27  v1.3  <axel.hahn@unibe.ch>      shell fixes; add help page
# 2023-10-13  v1.4  <axel.hahn@unibe.ch>      fix syntax error in export
# ======================================================================


. $( dirname $0 )/inc_pluginfunctions

export self_APPVERSION=1.4

tmpfile=/tmp/check_netstat_out_$$
infofile=/tmp/check_netstat_out_2_$$
myHost=$( hostname -f )

# set default / override from command line params
typeset -i iWarnLimit;     iWarnLimit=$(     ph.getValueWithParam  300 w "$@")
typeset -i iCriticalLimit; iCriticalLimit=$( ph.getValueWithParam 1000 c "$@")

rm -f $tmpfile $infofile 2>/dev/null

typeset -i iMax=0
typeset -i iTime=0

typeset -i iCounter=0
typeset -i iNotReachable=0

# show help
function showHelp(){
    local _self; _self=$(basename $0)
    cat <<EOF
$( ph.showImlHelpHeader )

Loop over all defined dns servers (in /etc/resolv.conf) and check
each:
  - detect of port 53 is available (DNS service)
  - 5x check time of a nslookup for current host (${myHost})

The a warning / critical response will be reached if the maximum time
of nslookup on the first dns server reaches a limit.

The critical response will be returned if the first of the 
nameservers is not available.

An unknown response will be returned if the current hostname 
(hostname -f) is no FQDN.

SYNTAX:
$_self [ -w VALUE -c VALUE -h ]

OPTIONS:

    -w VALUE       warning level  (default: 300)
    -c VALUE       critical level (default: 1000)
    -h or --help   Show this help.

EOF
}

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


# --- check param -h
case "$1" in
    "--help"|"-h")
        showHelp
        exit 0
        ;;
    *)
esac

if ! echo $myHost | cut -f 3- -d "." | grep "\." >/dev/null; then
    ph.setStatus unknown
    ph.status "DNS check for [$myHost] - SKIP: hostname -f returned a FQDN with less than 2 dots"
    ph.exit
fi

ph.require nslookup

for mydns in $(grep ^nameserver /etc/resolv.conf | awk '{ print $2 } ' )
do
    iCounter=$iCounter+1
    typeset -i iSrvMax=0
    echo "" >>$infofile

    echo "---------- $iCounter - $mydns " >>$infofile
    # todo loop
    if ! >/dev/tcp/${mydns}/53 >>$infofile 2>&1; then
      iNotReachable=$iNotReachable+1
      test $iCounter -eq 1 && ph.setStatus critical
      echo "ERROR: ${mydns} is not reachable on tcp 53" >>$infofile
    else
        for i in $(seq 5)
        do
            (time nslookup ${myHost} $mydns) >$tmpfile 2>&1

            iTime=$(cat $tmpfile | grep "^real.*m.*\..*s" | cut -f 2 -d "m" | sed "s#[\.s]##g" | sed "s#^0*##g" )
            echo "$mydns #$i >>> $iTime ms" >>$infofile
            test $iTime -ge $iWarnLimit && cat $tmpfile | grep -vE "^(real|user|sys)" >> $infofile
            test $iTime -gt $iSrvMax && iSrvMax=$iTime

        done
        echo "max: $iSrvMax ms" >>$infofile

        # --- set status
        test $iCounter -eq 1 && ph.setStatusByLimit $iSrvMax $iWarnLimit $iCriticalLimit

        label=${mydns//\./-}
        ph.perfadd "response-$label" "${iSrvMax}"
        test $iSrvMax -gt $iMax && iMax=$iSrvMax
    fi
    test $iCounter -eq 1 && (echo " ^"; echo " :"; echo " +--- 1st nameserver is relevant for total status of the check. Limits are warning=$iWarnLimit and critical=$iCriticalLimit") >>$infofile
    echo "" >>$infofile
done


test $iNotReachable -eq 0 && ph.status "DNS check for $myHost - found maximum was $iMax ms - OK: all nameservers are reachable"
test $iNotReachable -ne 0 && ph.status "DNS check for $myHost - found maximum was $iMax ms - INFO: $iNotReachable of $iCounter nameservers not reachable"
cat $infofile

rm -f $tmpfile $infofile


ph.exit

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