72 lines
2.9 KiB
Text
72 lines
2.9 KiB
Text
|
|
#!/bin/bash
|
||
|
|
# GENERE par Set-OPS (role chrony). Ne pas editer a la main.
|
||
|
|
#
|
||
|
|
# SONDE « horloge » — la machine est-elle synchronisee, ET contre LA SOURCE DECLAREE ?
|
||
|
|
#
|
||
|
|
# LES DEUX MOITIES COMPTENT. Une machine peut etre parfaitement a l'heure en interrogeant
|
||
|
|
# quatre serveurs publics : c'est le defaut de Debian, et il a tenu quatorze machines
|
||
|
|
# jusqu'au 2026-09-11 sans que rien ne le dise. Mesurer la seule derive laisserait ce
|
||
|
|
# retour en arriere invisible.
|
||
|
|
#
|
||
|
|
# POURQUOI L'HEURE MERITE UNE SONDE. step-ca emet des certificats a duree courte ; TLS
|
||
|
|
# refuse un certificat pas encore valide ; Loki rejette une ligne trop loin dans le futur ;
|
||
|
|
# les silences d'Icinga reposent sur des `ttl`. Une flotte dont les horloges divergent
|
||
|
|
# tombe en panne de l'interieur, avec des symptomes qui ressemblent a tout sauf a une
|
||
|
|
# horloge.
|
||
|
|
#
|
||
|
|
# Contrat : docs/supervision-conception.md (API des greffons Nagios) — une ligne, 0/1/2.
|
||
|
|
# Mise en defaut PAR PARAMETRE : `chrony_sonde_ecart_max` (le baisser a 0).
|
||
|
|
set -uo pipefail
|
||
|
|
|
||
|
|
ECART_MAX={{ chrony_sonde_ecart_max }}
|
||
|
|
ATTENDUS="{{ chrony_serveurs | join(' ') }}"
|
||
|
|
|
||
|
|
if ! systemctl is-active --quiet chrony; then
|
||
|
|
echo "chrony ne tourne pas : l'horloge derive sans que personne ne la corrige." \
|
||
|
|
"| ecart=U sources=0 declarees=0"
|
||
|
|
exit 2
|
||
|
|
fi
|
||
|
|
|
||
|
|
# `^*` marque la source RETENUE. Sans elle, chrony tourne mais ne suit personne.
|
||
|
|
retenue=$(chronyc -n sources 2>/dev/null | awk '/^\^\*/ {print $2; exit}')
|
||
|
|
sources=$(chronyc -n sources 2>/dev/null | tail -n +3 | wc -l)
|
||
|
|
|
||
|
|
if [[ -z "${retenue}" ]]; then
|
||
|
|
echo "chrony tourne mais n'a retenu AUCUNE source (${sources} candidate(s)) :" \
|
||
|
|
"l'heure n'est plus disciplinee." \
|
||
|
|
"| ecart=U sources=${sources} declarees=0"
|
||
|
|
exit 2
|
||
|
|
fi
|
||
|
|
|
||
|
|
# L'ecart en millisecondes, en valeur absolue.
|
||
|
|
ecart=$(chronyc tracking 2>/dev/null \
|
||
|
|
| awk '/^Last offset/ {o=$4+0; if (o<0) o=-o; printf "%.0f", o*1000}')
|
||
|
|
# `$4+0` FORCE LE NUMERIQUE. `chronyc` prefixe la valeur d'un `+` ou d'un `-` ; sans la
|
||
|
|
# conversion, awk compare une CHAINE a zero et la valeur absolue ne mord pas. Le symptome
|
||
|
|
# etait discret — `ecart=-0ms` en perfdata — et c'est precisement ce qu'un grapheur avale
|
||
|
|
# sans rien dire.
|
||
|
|
ecart=${ecart:-0}
|
||
|
|
|
||
|
|
declarees=0
|
||
|
|
for s in ${ATTENDUS}; do
|
||
|
|
[[ "${retenue}" == "${s}" ]] && declarees=1
|
||
|
|
done
|
||
|
|
|
||
|
|
if [[ -n "${ATTENDUS}" && "${declarees}" -eq 0 ]]; then
|
||
|
|
echo "L'heure vient de ${retenue}, qui n'est PAS la source declaree (${ATTENDUS}) :" \
|
||
|
|
"la machine est sortie de l'ecosysteme pour se synchroniser." \
|
||
|
|
"| ecart=${ecart}ms;${ECART_MAX} sources=${sources} declarees=0"
|
||
|
|
exit 2
|
||
|
|
fi
|
||
|
|
|
||
|
|
if (( ecart > ECART_MAX )); then
|
||
|
|
echo "Synchronisee sur ${retenue}, mais l'ecart atteint ${ecart} ms" \
|
||
|
|
"(seuil ${ECART_MAX} ms) : les certificats a duree courte vont souffrir." \
|
||
|
|
"| ecart=${ecart}ms;${ECART_MAX} sources=${sources} declarees=1"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "Horloge disciplinee par ${retenue}, ecart ${ecart} ms." \
|
||
|
|
"| ecart=${ecart}ms;${ECART_MAX} sources=${sources} declarees=1"
|
||
|
|
exit 0
|