|
#!/bin/sh |
|
# |
|
# Nom: menu.sh |
|
# Auteur : Gaetan RYCKEBOER |
|
# Role : superviser l'horloge locale par rapport a un pool de serveurs internet |
|
# Date : 06.02.2013 |
|
# Version : 1.19 |
|
# |
|
# Root : non |
|
# |
|
# |
|
# Historique |
|
# Version | Date | Ref. | Qui | Description |
|
# v1.0 | 20.08.10 | | GRY | Creation |
|
# v1.1 | 23.08.10 | | GRY | send email |
|
# v1.2 | 27.08.10 | | GRY | Supervision NTP |
|
# v1.3 | 30.08.10 | | GRY | Better NTP monitoring |
|
# v1.4 | 01.09.10 | | GRY | Add "crossover" ntp |
|
# v1.5 | 08.09.10 | | GRY | better reach monitoring |
|
# v1.6 | 08.09.10 | | GRY | Refactor ntpq per line checks |
|
# v1.7 | 09.09.10 | | GRY | Remove completely out clock sources |
|
# v1.8 | 11.09.10 | | GRY | Ajout courriel en cas d'erreur |
|
# v1.9 | 11.09.10 | | GRY | Suppression des alertes NTP si reach trop faible |
|
# v1.10 | 14.09.10 | | GRY | Ajout de la variable "flash" |
|
# v1.11 | 20.09.10 | | GRY | Si reach > 0, pas d'erreur "unreach". On suppose que c'est transitoire. |
|
# v1.12 | 30.10.10 | | GRY | Ajout supervision demon NTP uniquement |
|
# v1.13 | 13.12.10 | | GRY | Incompatibilite syntaxe anciens ksh [ '==' ] |
|
# v1.14 | 04.01.11 | | GRY | Incompatibilite syntaxe anciens ksh [ '==' ] |
|
# v1.15 | 03.05.11 | | GRY | Factorisation gestion demon ntp |
|
# v1.16 | 26.07.12 | | GRY | Fix [ " " ] |
|
# v1.17 | 18.01.13 | | GRY | exit 1 on GetHTTPDate and shift |
|
# v1.18 | 06.02.13 | | GRY | Help + remove yahoo |
|
# v1.19 | 20.06.18 | | GRY | Change \n to end of line, fix ntpq clocks ID, english translation |
|
# |
|
|
|
# Affichage des details |
|
VERBOSE=false |
|
# Affichage des lignes |
|
DEBUG=false |
|
# Ce qui sera envoye par courriel |
|
RETOUR=""; |
|
# ERR=ERROR or ERR="" selon la gravite des erreurs |
|
ERR="" |
|
# Version du script |
|
VERSION=$(egrep '^# Version :' $0 | cut -d ':' -f 2 | tr -d ' ') |
|
|
|
# Emplacement des binaires |
|
NTPQx="/usr/bin/ntpq /usr/sbin/ntpq" |
|
NTPDx="/usr/bin/ntpd /usr/sbin/xntpd /usr/bin/xntpd /usr/sbin/ntpd" |
|
|
|
for i in $NTPDx ; do |
|
[ -x "$i" ] && NTPD=$i |
|
done |
|
|
|
for i in $NTPQx ; do |
|
[ -x "$i" ] && NTPQ=$i |
|
done |
|
|
|
|
|
########### |
|
# Some constants |
|
|
|
URL_LIST="www.google.com www.viamichelin.com www.ibm.com www.pool.ntp.org" |
|
HTTP_PROXY=$http_proxy # Local proxy varibale. Must be set. |
|
MailFrom="From: \"EXPLOIT\" <[email protected]>" |
|
MaxSecOffset=5 # Max number of seconds between HTTP check and local time |
|
MinNTPReach=1 # Minimal number of servers to be reached |
|
export LANG=C;export LC_ALL=C |
|
|
|
HTTP_PROXY_PORT=$(echo $HTTP_PROXY | cut -d / -f 3| cut -d : -f 2) |
|
HTTP_PROXY=$(echo $HTTP_PROXY | cut -d / -f 3| cut -d : -f 1) |
|
|
|
|
|
##### Goal #### |
|
# to provide two tools for date/time monitoring: |
|
# - ntpq daemon quality analysis |
|
# - date/time queries thru HTTP headers for time reliancy |
|
# |
|
##### Usage remarks #### |
|
# This piece of sofware may work with minimal modifications on AIX, as it was intended to work on this platform on first write. |
|
# It NEEDS a $http_proxy variable set to work for distant HTTP queries, as it requests this proxy for all http headers. |
|
# |
|
##### Examples #### |
|
# to check date/time from distant HTTP queries: |
|
# get_http_date.sh -d -v |
|
# |
|
# to check NTP Quality |
|
# get_http_date.sh -d -N |
|
# |
|
# to check quality and send mails only on error to exploit mailbox |
|
# get_http_date.sh -N -M |
|
# |
|
##### Dependencies #### |
|
# - bc -- calculator |
|
# - host -- hostname/ips query tools |
|
# - perl-HTTP-Date -- Date manipulation perl module HTTP::Date |
|
# |
|
|
|
########### |
|
|
|
Help() { |
|
echo "$(basename $0) version $VERSION" |
|
echo >&2 "Usage: $0 [-d] [-D] [-m mailto@domain] [-M mailto@domain] [-n] [-v]" |
|
echo >&2 " $0 [-d] [-D] [-h] |
|
|
|
-d : verbose |
|
-D : debug |
|
-m : send result by email |
|
-M : idem but only on error |
|
-n : NTP daemon monitoring |
|
-N : NTP clocks quality monitoring |
|
-v : HTTP check of time and date |
|
-h : help / aide" |
|
} |
|
|
|
|
|
ValidateNTP() { |
|
|
|
NTPDisabled=0 |
|
NTPSpare=0 |
|
NTPValides=0 |
|
NTPOff=0 |
|
NTPReach=0 |
|
|
|
$DEBUG && set -x |
|
NTPError="" |
|
if ValidateNTPDaemon ; then |
|
|
|
NTPServers=$($NTPQ -np | egrep -v ' reach +delay +offse' |grep -v '=========' 2>/dev/null | sed 's/^\(.\)/[\1] /' ) |
|
NTPHead=$($NTPQ -np | egrep ' reach +delay +offse') |
|
|
|
##################################################################################################### |
|
# Nouvelle boucle par ligne du ntpq |
|
$VERBOSE && RETOUR="$RETOUR |
|
Ntpq :" |
|
NTPServers2="sta$NTPHead - hostname" |
|
for line in $(echo "$NTPServers" | sed 's/\[ \]/[@]/;s/ /%/g' ) ; do |
|
line="$(echo $line | sed 's/%/ /g')" |
|
status=$(echo $line | awk '{print $1}'|tr '@' ' ') |
|
host=$(echo $line | awk '{print $2}') |
|
# Specifique AIX |
|
##hostname=$(host $host 2>/dev/null| tail -n 1 | cut -d ' ' -f 1| cut -d '.' -f -2) |
|
hostname=$((host $host 2>i/dev/null||echo $host )|tail -n 1|sed 's/.*name pointer \(.*\)/\1/') |
|
#hostname=$(dig +short -x $host 2>/dev/null) |
|
refid=$(echo $line | awk '{print $3}') |
|
stratum=$(echo $line | awk '{print $4}') |
|
type=$(echo $line | awk '{print $5}') |
|
when=$(echo $line | awk '{print $6}') |
|
poll=$(echo $line | awk '{print $7}') |
|
reach=$(echo $line | awk '{print $8}') |
|
delay=$(echo $line | awk '{print $9}') |
|
offset=$(echo $line | awk '{print $10}') |
|
disp=$(echo $line | awk '{print $11}') |
|
|
|
NTPServers2="$NTPServers2 |
|
$(echo "$line" | sed "s/^\[@\]/[ ]/;s/\(^... $host .*\)/\\1 - $( echo $hostname| cut -d '.' -f -2)/")" |
|
|
|
# Les serveurs valides |
|
if echo "$status" | egrep "[\*o#]" >/dev/null 2>&1 ; then |
|
((NTPValides=NTPValides+1)) |
|
if [ "$type" = "l" -o "$type" = "-" ] ; then |
|
NTPError="$NTPError |
|
ERROR : The reference clock is localhost" |
|
ERR=ERROR |
|
ERRlocal=1 |
|
fi |
|
fi |
|
# Serveurs de spare |
|
echo "$status" | egrep "[\+]" >/dev/null 2>&1 && \ |
|
((NTPSpare=NTPSpare+1)) |
|
# Serveurs desactives par le crossover |
|
if echo "$status" | egrep "[xX]" >/dev/null 2>&1 ; then |
|
((NTPDisabled=NTPDisabled+1)) |
|
NTPError="$NTPError |
|
ERROR : the server $hostname ($host) is declared 'invalid' $status" |
|
ERR=ERROR |
|
fi |
|
if echo "$type" | grep "-" >/dev/null 2>&1 ; then |
|
$VERBOSE && NTPError="$NTPError |
|
INFO : $hostname ($host) configuration is slightly out of phase Type: '-'" |
|
else |
|
# conversion la colonne "reach" en binaire, et on compte les "1". |
|
NTPReachBin=$(printf "%08d" $(echo "obase=2;ibase=8;$reach" | bc )) |
|
let NTPReachNum=$(echo "$NTPReachBin" | tr '1' ' |
|
' | wc -l | tr -d ' ')-1 |
|
$VERBOSE && RETOUR="$RETOUR |
|
reach : $(printf "%30s - %3d" $hostname $reach) - #${NTPReachBin} - $NTPReachNum" |
|
# Moins de 6/8 reponses : on alerte |
|
if [ "$NTPReachNum" -lt "$MinNTPReach" ] ; then |
|
ERR=ERROR |
|
NTPError="$NTPError |
|
ERROR : the clock serverl $hostname ($host) is not reliable |
|
: reach=$(printf '%3d' $reach) means the following sequence '#$(echo $NTPReachBin|tr '0' '.' |tr '1' 'X' )' ; $NTPReachNum responses" |
|
# On n'alerte que si le serveur est totalement injoignable |
|
else |
|
let NTPReach=$NTPReach+1 |
|
fi |
|
|
|
# Serveurs injoignables / cf disp et reach |
|
if echo "$status" | egrep "^\[ \]" >/dev/null 2>&1 ; then |
|
((NTPOff=NTPOff+1)) |
|
if [ "$type" != 'l' ] ; then |
|
NTPError="$NTPError |
|
WARN : The clock of $hostname ($host) is not suitable for synchronization $status" |
|
# Dans ce cas, on affiche aussi la colonne reach |
|
NTPError="$NTPError |
|
DEBUG : reach=$(printf '%3d' $reach) means the following sequence '#$(echo $NTPReachBin|tr '0' '.' |tr '1' 'X' )' ; $NTPReachNum responses" |
|
fi |
|
fi |
|
fi |
|
done |
|
############################### |
|
# Serveurs de reference |
|
[ "$NTPValides" -lt 1 ] && NTPError="$NTPError |
|
ERROR : no reference clock server" && ERR=ERROR |
|
# Serveurs de secours |
|
[ "$NTPSpare" -lt 1 ] && NTPError="$NTPError |
|
WARN : Not enough backup servers" |
|
# Serveurs inactifs |
|
[ "$NTPOff" -gt 1 ] && NTPError="$NTPError |
|
WARN : some servers are not reliable" |
|
# Serveurs desactives |
|
[ "$NTPDisabled" -gt 3 ] && NTPError="$NTPError |
|
WARN : Too many 'bad clock' servers" |
|
# Serveurs joignables |
|
[ "$NTPReach" -lt 3 ] && NTPError="$NTPError |
|
WARN : Not reachable servers enough" |
|
##################################################################################################### |
|
|
|
if [ "" != "$NTPError" ] ; then |
|
# Recuperons la liste des ID |
|
NTPError="$NTPError |
|
|
|
DEBUG : FLASH" |
|
# Recuperons la liste des ID |
|
for assID in $($NTPQ -nc 'as' | grep -v '====' | grep -vi 'ind assID' | tr -s ' ' | cut -d ' ' -f 3 ) ; do |
|
# Pour chaque ID on recupere le flash et l'IP |
|
NTPQLIST=$($NTPQ -nc "rv $assID" ) |
|
#NTPQLIST=$($NTPQ -nc "rv $assID" ) |
|
IP=$(echo "$NTPQLIST"|egrep 'srcadr=' | sed 's/.*srcadr=\([^,]*\),.*/\1/') |
|
FLASH=$(echo "$NTPQLIST"|egrep 'flash=' | sed 's/.* flash=\([^,<]*\)\(<.*>\),.*/\1 - \2/') |
|
NTPError="$NTPError |
|
: $IP - $FLASH" |
|
done |
|
if [ "$ERR" = "ERROR" ] ; then |
|
RETOUR="$RETOUR |
|
|
|
ERROR : Probleme sur NTP" |
|
else |
|
RETOUR="$RETOUR |
|
|
|
WARN : Probleme sur NTP" |
|
fi |
|
RETOUR="$RETOUR |
|
$NTPError |
|
|
|
Joignables:$NTPReach Valide:$NTPValides Secours:$NTPSpare Inutilisables:$NTPOff Desactives:$NTPDisabled" |
|
RETOUR="$RETOUR |
|
min.......:3 min...:1 min....:1 .............:- max.......:0 |
|
" |
|
RETOUR="$RETOUR |
|
$NTPServers2 |
|
" |
|
#ERR=ERROR |
|
else $VERBOSE && RETOUR="$RETOUR |
|
$NTPServers2 |
|
" |
|
fi |
|
else |
|
#RETOUR="$RETOUR |
|
#ERROR : Le demon NTP n'est pas demarre" |
|
#ERR=ERROR |
|
: |
|
fi |
|
} |
|
|
|
ValidateNTPDaemon() { |
|
NTPError="" |
|
if ps -ef | grep -v grep | grep $NTPD >/dev/null ; then |
|
: |
|
true |
|
else |
|
RETOUR="$RETOUR |
|
ERROR : NTP daemon is not running" |
|
ERR=ERROR |
|
false |
|
fi |
|
} |
|
|
|
GetHTTPDate() { |
|
$DEBUG && set -x |
|
( sleep 1 ; echo "HEAD / HTTP/1.1" ; echo "Host: $1" ; echo ; echo "quit" ; sleep 1 ) | \ |
|
telnet $HTTP_PROXY $HTTP_PROXY_PORT 2>/dev/null| grep Date: |\ |
|
awk '{print $2" "$3" "$4" "$5" "$6" "$7}' | perl -pe 'use HTTP::Date;$_=str2time($_)+1' |
|
# On est oblige d'ajouter une seconde de "sleep 1" pour la fin de telnet |
|
} |
|
|
|
ValidateDateTime() { |
|
Diff=0 |
|
NbDiff=0 |
|
SvrDiff=0 |
|
DateSVR=0 |
|
$DEBUG && set -x |
|
for HostName in $URL_LIST ; do |
|
DateHTTP=$( GetHTTPDate "$HostName" ) |
|
LocalDate=$( date -u | perl -pe 'use HTTP::Date;$_=str2time($_)') |
|
let DateDiff=$DateHTTP-$LocalDate ; |
|
$VERBOSE && RETOUR="$RETOUR |
|
$HostName : $DateDiff" >&2 |
|
# Si le décalage est trop important ET que le serveur HTTP a répondu correctemet, |
|
if [ "$( echo $DateDiff | tr -d '-' )" -gt "$MaxSecOffset" -a "$DateHTTP" -gt 10 ] ; then |
|
# le decalage est trop important |
|
let NbDiff=$NbDiff+1 |
|
RETOUR="$RETOUR |
|
WARN : Clock server $HostName is out of synchronization with $(hostname) ($DateDiff seconds)" |
|
DateSVR=$DateDiff |
|
fi |
|
done |
|
|
|
if [ "$NbDiff" -gt 1 ] ; then |
|
# Plus de un serveur en decalage |
|
RETOUR="$RETOUR |
|
ERROR : System clock is out of phase from $NbDiff sources." |
|
ERR=ERROR |
|
RETOUR="$RETOUR |
|
stopsrc -s xntpd ; date -u -a $DateSVR ; sleep 3000 ; startsrc -s xntpd" |
|
fi |
|
} |
|
|
|
########################################################################################## |
|
|
|
while getopts :m:M:dhnNDv o |
|
do case "$o" in |
|
m) MailTo="$OPTARG";; |
|
N) ValidateNTP;; |
|
n) ValidateNTPDaemon;; |
|
v) ValidateDateTime;; |
|
d) VERBOSE=true;; |
|
D) DEBUG=true;; |
|
M) MailErr="$OPTARG";; |
|
[?]|h) Help |
|
exit 1;; |
|
esac |
|
done |
|
let T=$OPTIND-1 |
|
shift $T |
|
# shift $OPTIND |
|
|
|
$DEBUG && echo $NTPQ $NTPD |
|
|
|
|
|
########## |
|
|
|
|
|
if [ ! "$MailErr" = "" ] && [ "$ERR" = "ERROR" ] ; then |
|
if [ "$MailTo" = "" ] ; then |
|
MailTo="$MailErr" |
|
else |
|
MailTo="$MailTo,$MailErr" |
|
fi |
|
fi |
|
if [ ! "$MailTo" = "" ] && [ ! "$RETOUR" = "" ] ; then |
|
echo "From: $MailFrom |
|
To: $(echo "$MailTo" | sed 's/,/\ |
|
Cc: /g' ) |
|
Content-Type: text/html |
|
Subject: [NTP] ${ERR} out of phase synchronization - $(hostname) |
|
|
|
<p>Clock monitoring for serveur <b>$(hostname)</b> |
|
|
|
<p>See : <a href=\"http://wikidoc.foo.bar/wiki/NTP\">NTP wiki documention</a> |
|
|
|
|
|
<li>$(date) |
|
<li>$(date -u) |
|
<li>$TZ |
|
</ul> |
|
<hr noshade> |
|
<pre> |
|
$RETOUR |
|
|
|
|
|
</pre> |
|
<hr noshade> |
|
Monitoring robot (version $VERSION) |
|
<html> |
|
" | tee /tmp/toto.ntp | /usr/lib/sendmail -ba -f "$MailFrom" -t |
|
fi |
|
|
|
if [ "$RETOUR" = "" -a "$ERR" = "" ] ; then |
|
$VERBOSE && echo OK. |
|
$VERBOSE && echo "$RETOUR" |
|
else |
|
[ "$MailTo" = "" ] && echo "$RETOUR |
|
Version : $VERSION" |
|
if echo "$RETOUR$ERR" | grep ERROR ; then |
|
exit 1 |
|
fi |
|
fi |
|
|
|
exit 0 |