Archivi tag: delay

check_ntp_peers: script bash per il monitoraggio dei peer NTP mediante Nagios

Il protocollo NTP ci consente, in soldoni, di tenere aggiornate la data e l’ora di sistema, sincronizzandole con un’apposita sorgente di tempo. Per i sistemi *nix, nella stragrande maggioranza dei casi, è sufficiente configurare il servizio NTP (attivo mediante il demone ntpd, o, in alternativa, utilizzando l’accoppiata ntpdate + crontab) agendo sul suo file diconfigurazione (ovvero ntp.conf) e definendo le sorgenti alle quali sincronizzarsi.

ntpAd esempio:

server ntp1.inrim.it
server ntp2.inrim.it

Ora, per saggiare lo stato di sincronizzazione del nostro server, a parte il classico comando date, è possibile utilizzare un apposito tool per le interrogazioni NTP, ovvero ntpq:

[root@linuxbox ~]# ntpq
ntpq> pe
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*ntp1.inrim.it   .CTD.            1 u    4   64  377   45.819    0.219   2.655
+ntp2.inrim.it   .CTD.            1 u  903 1024  377   48.974    1.788   0.978

In particolare, con il comando pe, sono riuscito a recuperare la lista dei peers (ovvero le sorgenti di tempo) con i relativi valori di offset (i quali rappresentano la discrepanza, in ms, tra l’ora locale di sistema e quella del peer stesso), di jitter (ovvero il ritardo, anch’esso espresso in ms, accumulato tra 2 aggiornamenti immediatamente successivi) e di delay (RTT, in ms, associato alla comunicazione con il time server remoto). Da notare, inoltre, che il campo refid indica qual è (se esiste, dipende dallo stratum, specificato dal campo st) la sorgente di tempo utilizzata a loro volta dai server che sto interrogando (rispettivamente ntp1.inrim.it ed ntp2.inrim.it), mentre il carattere * mostra quale dei 2 server da me definiti all’interno del file ntp.conf sto utilizzando per sincronizzare la data e l’ora di sistema.

Dopo questa breve carrellata introduttiva veniamo al dunque, per cui riporto il contenuto dello scrip bash in grado di tenere sotto controllo i valori associati alle sorgenti NTP definite sul nostro sistema:

#!/bin/bash

warn_values=$1
crit_values=$2

warn_delay=`echo $warn_values | awk -F "," '{print $1}'`
warn_offset=`echo $warn_values | awk -F "," '{print $2}'`
warn_jitter=`echo $warn_values | awk -F "," '{print $3}'`

warn_delay_len=$((${#warn_delay} - 1))
warn_offset_len=$((${#warn_offset} - 1))
warn_jitter_len=$((${#warn_jitter} - 1))

crit_delay=`echo $crit_values | awk -F "," '{print $1}'`
crit_offset=`echo $crit_values | awk -F "," '{print $2}'`
crit_jitter=`echo $crit_values | awk -F "," '{print $3}'`

crit_delay_len=$((${#crit_delay} - 1))
crit_offset_len=$((${#crit_offset} - 1))
crit_jitter_len=$((${#crit_jitter} - 1))

if [[ "$warn_delay_len" -gt 5 ]];then
        echo "UNKNOWN: bad value for warning delay"
        echo "Usage: check_ntp_peers warndelay,warnoffset,warnjitter critdelay,critoffset,critjitter"
        exit 3;
fi

if [[ "$warn_offset_len" -gt 5 ]];then
        echo "UNKNOWN: bad value for warning offset"
        echo "Usage: check_ntp_peers warndelay,warnoffset,warnjitter critdelay,critoffset,critjitter"
        exit 3;
fi

if [[ "$warn_jitter_len" -gt 5 ]];then
        echo "UNKNOWN: bad value for warning jitter"
        echo "Usage: check_ntp_peers warndelay,warnoffset,warnjitter critdelay,critoffset,critjitter"
        exit 3;
fi

if [[ "$crit_delay_len" -gt 5 ]];then
        echo "UNKNOWN: bad value for critical delay"
        echo "Usage: check_ntp_peers warndelay,warnoffset,warnjitter critdelay,critoffset,critjitter"
        exit 3;
fi

if [[ "$crit_offset_len" -gt 5 ]];then
        echo "UNKNOWN: bad value for critical offset"
        echo "Usage: check_ntp_peers warndelay,warnoffset,warnjitter critdelay,critoffset,critjitter"
        exit 3;
fi

if [[ "$crit_jitter_len" -gt 5 ]];then
        echo "UNKNOWN: bad value for critical jitter"
        echo "Usage: check_ntp_peers warndelay,warnoffset,warnjitter critdelay,critoffset,critjitter"
        exit 3;
fi

ntp_delay=`/usr/sbin/ntpq -p | grep '*' | awk '{print $8}'`
ntp_offset=`/usr/sbin/ntpq -p | grep '*' | awk '{print $9}'`
ntp_jitter=`/usr/sbin/ntpq -p | grep '*' | awk '{print $10}'`

if [[ ! -z $warn_values ]];then
         if [[ ! -z $crit_values ]];then
                if [[ ! -z $warn_delay ]];then
                        if [[ ! -z $crit_delay ]];then
                                if [[ "$(echo $ntp_delay '>=' $warn_delay | bc)" -eq 1 ]] && [[ "$(echo $ntp_delay '<' $crit_delay | bc)" -eq 1 ]];then
                                        delay="NTP delay is $ntp_delay ms";
                                        delay_perf="| ntp_delay=$ntp_delay"
                                        retval_1=1;
                                elif [[ "$(echo $ntp_delay '>=' $crit_delay | bc)" -eq 1 ]];then
                                        delay="NTP delay is $ntp_delay ms";
                                        delay_perf="| ntp_delay=$ntp_delay"
                                        retval_1=2;
                                else
                                        delay="NTP delay is $ntp_delay ms";
                                        delay_perf="| ntp_delay=$ntp_delay"
                                        retval_1=0;
                                fi
                        else
                                echo "UNKNOWN: NTP critical delay is unknown"
                                exit 3;
                        fi
                else
                        echo "UNKNOWN: NTP warning delay is unknown"
                        exit 3;
                fi
                if [[ ! -z $warn_offset ]];then
                        if [[ ! -z $crit_offset ]];then
                                if [[ "$(echo $ntp_offset '<' 0 | bc)" -eq 1 ]];then
                                        warn_offset=$(echo "-1 * $warn_offset" | bc)
                                        crit_offset=$(echo "-1 * $crit_offset" | bc)
                                        if [[ "$(echo $ntp_offset '<=' $warn_offset | bc)" -eq 1 ]] && [[ "$(echo $ntp_offset '>' $crit_offset | bc)" -eq 1 ]];then
                                                offset="NTP offset is $ntp_offset ms";
                                                offset_perf=" ntp_offset=$ntp_offset"
                                                retval_2=1;
                                        elif [[ "$(echo $ntp_offset '<' $crit_offset | bc)" -eq 1 ]];then
                                                offset="NTP offset is $ntp_offset ms";
                                                offset_perf=" ntp_offset=$ntp_offset"
                                                retval_2=2;
                                        else
                                                offset="NTP offset is $ntp_offset ms";
                                                offset_perf=" ntp_offset=$ntp_offset"
                                                retval_2=0;
                                        fi
                                else
                                        if [[ "$(echo $ntp_offset '>=' $warn_offset | bc)" -eq 1 ]] && [[ "$(echo $ntp_offset '<' $crit_offset | bc)" -eq 1 ]];then
                                                offset="NTP offset is $ntp_offset ms";
                                                offset_perf=" ntp_offset=$ntp_offset"
                                                retval_2=1;
                                        elif [[ "$(echo $ntp_offset '>' $crit_offset | bc)" -eq 1 ]];then
                                                offset="NTP offset is $ntp_offset ms";
                                                offset_perf=" ntp_offset=$ntp_offset"
                                                retval_2=2;
                                        else
                                                offset="NTP offset is $ntp_offset ms";
                                                offset_perf=" ntp_offset=$ntp_offset"
                                                retval_2=0;
                                        fi
                                fi
                        else
                                echo "UNKNOWN: NTP critical offset is unknown"
                                exit 3;
                        fi
                else
                        echo "UNKNOWN: NTP warning offset is unknown"
                        exit 3;
                fi
                if [[ ! -z $warn_jitter ]];then
                        if [[ ! -z $crit_jitter ]];then
                                if [[ "$(echo $ntp_jitter '>' $warn_jitter | bc)" -eq 1 ]] && [[ "$(echo $ntp_jitter '<' $crit_jitter | bc)" -eq 1 ]];then
                                        jitter="NTP jitter is $ntp_jitter ms";
                                        jitter_perf=" ntp_jitter=$ntp_jitter"
                                        retval_3=1;
                                elif [[ "$(echo $ntp_offset '>' $crit_jitter | bc)" -eq 1 ]];then
                                        jitter="NTP jitter is $ntp_jitter ms";
                                        jitter_perf=" ntp_jitter=$ntp_jitter"
                                        retval_3=2;
                                else
                                        jitter="NTP jitter is $ntp_jitter ms";
                                        jitter_perf=" ntp_jitter=$ntp_jitter"
                                        retval_3=0;
                                fi
                        else
                                echo "UNKNOWN: NTP critical jitter is unknown"
                                exit 3;
                        fi
                else
                        echo "UNKNOWN: NTP warning jitter is unknown"
                        exit 3;
                fi
        else
                 echo "UNKNOWN: Critical values are unknown"
                 echo "Usage: check_ntp_peers warndelay,warnoffset,warnjitter critdelay,critoffset,critjitter"
                 exit 3;
        fi
else
        echo "UNKNOWN: Warning values are unknown"
        echo "Usage: check_ntp_peers warndelay,warnoffset,warnjitter critdelay,critoffset,critjitter"
        exit 3;
fi

if [[ "$retval_1" -eq 1 ]] || [[ "$retval_2" -eq 1 ]] || [[ "$retval_3" -eq 1 ]];then

        echo "WARNING: $delay $offset $jitter $delay_perf $offset_perf $jitter_perf"
        exit 1

elif [[ "$retval_1" -eq 2 ]] || [[ "$retval_2" -eq 2 ]] || [[ "$retval_3" -eq 2 ]];then

        echo "CRITICAL: $delay $offset $jitter $delay_perf $offset_perf $jitter_perf"
        exit 2

else

        echo "OK: $delay $offset $jitter $delay_perf $offset_perf $jitter_perf"
        exit 0

fi

Per prima cosa viene verificata la consistenza delle soglie di WARNING e CRITICAL per ciauscuno dei 3 valori monitorati (offset, jitter e delay), sia per quanto riguarda il numero di cifre utilizzate (5) che per ciò che concerne la coerenza logica (ad esempio il jitter/offset/delay di WARNING deve essere strettamente minore di quello CRITICAL).

A questo punto non ci rimane che configurare Nagios, editando, in prima istanza, il file /etc/nagios/objects/commands.cfg, dove verrà definito il comando che si avvarrà del suddetto plugin:

 # 'check_ntp_peers' command definition
define command{
        command_name check_ntp_peers
        command_line $USER1$/check_ntp_peers $ARG1$ $ARG2$
}

e successivamente associando uno specifico servizio all’host che rappresenta la nostra macchina, in modo da monitorare i valori associati all’NTP:

define service{
        use                             local-service         ; Name of service template to use
        host_name                       localhost
        service_description             NTP Peers Status
        check_command                   check_ntp_peers!80.000,2.000,2.000!90.000,3.000,3.000
        }

Facciamo il solito reload del nostro NMS:

[root@linuxbox ~]# service nagios reload

ed abbiamo finito.

Alla prossima.

PS: ho deciso di scrivere il suddetto scrip per sopperire alle limitazioni intrinseche del plugin Nagios (nativo) check_ntp_peer (senza la s finale). Nella fattispecie, quest’ultimo consente di ricavare solo ed esclusivamente il valore di offset associato alla sorgente di tempo remota e per funzionare è necessario che il server interrogato sia configurato in modo da rispondere alle query NTP (e quindi non solo alle richieste di sincronizzazione). Da notare che, nella stragrande maggioranza dei casi e per questioni di sicurezza, il server consentirà la sola sincronizzazione, ignorando gli altri tipi di query, come riportato nero su bianco (ad esempio) nella configurazione standard di ntpd:

restrict default kod nomodify notrap nopeer noquery
restrict -6 default kod nomodify notrap nopeer noquery

NTP ed SNTP sync

Se il vostro enviroment possiede N macchine Windows con il servizio NTP attivo (quello nativo) ed una sorgente di sincronizzazione basata su un server SNTP (Simple Network Time Protocol), allora vedrete aumentare la deriva temporale (aka delay) a dismisura.

Infatti, è possibile consentire la sincronizzazione di un server SNTP da una sorgente NTP, MA NON VICEVERSA.

Alla prossima.