Mettre en place un monitoring serveur simple avec les outils du système
Un script de contrôle, un timer systemd et une voie d'alerte réellement testée suffisent pour un serveur root isolé. Ce guide montre ce qu'il faut surveiller, comment vérifier chaque étape et à partir de quand la grosse boîte à outils devient rentable.
Un serveur ne vous prévient pas de lui-même quand quelque chose déraille. Il continue de tourner jusqu'à ce qu'il ne tourne plus, et le premier retour vient d'un client ou de vous, le jour où vous regardez par hasard. Ce guide met en place le plus petit monitoring capable d'en finir avec cela : un script de contrôle, un timer systemd, une voie de notification. Pas de base de séries temporelles, pas de tableau de bord, pas de port ouvert supplémentaire.
Les systèmes de référence sont Debian 13 (trixie), Debian 12 (bookworm), Ubuntu 24.04 LTS et Ubuntu 22.04 LTS. Là où ces quatre systèmes divergent, c'est signalé explicitement. Toutes les commandes sont écrites pour une exécution en tant que root ; en utilisateur normal, faites précéder chaque commande d'un sudo. Ce guide approfondit l'étape 8 de la checklist pour un nouveau serveur root.
Ce qu'il faut réellement surveiller
L'erreur la plus fréquente sur un premier monitoring n'est pas d'en mesurer trop peu, mais d'en mesurer trop. Qui collecte 40 indicateurs n'en regarde aucun. Seul compte ce qui peut arrêter l'exploitation et ce sur quoi vous pouvez agir. Il reste sept points.
| Indicateur | Pourquoi il figure sur la liste | D'où vient la valeur | Seuil pertinent |
|---|---|---|---|
| Espace disque | La cause de panne la plus fréquente, et personne ne la voit venir | df --output=pcent,target | à partir de 85 % |
| Inodes | Disque apparemment libre, et pourtant « No space left on device » | df --output=ipcent,target | à partir de 85 % |
| RAM disponible | L'OOM killer frappe rarement le processus que vous auriez sacrifié | MemAvailable dans /proc/meminfo | en dessous de 200 MB |
| Charge système | Signale l'engorgement, que la cause soit le CPU ou le disque | troisième champ de /proc/loadavg | moyenne sur 15 minutes au-dessus du double du nombre de cœurs |
| Services en échec | Un service qui meurt la nuit reste mort jusqu'au matin | systemctl is-system-running | tout sauf running |
| Expiration du certificat | Bloque d'un coup tous les visiteurs, pas seulement une partie | openssl x509 -checkend | moins de 21 jours restants |
| Accessibilité depuis l'extérieur | Seul contrôle qui répond à la question de savoir si le serveur est encore là | second hôte, curl | deux échecs consécutifs |
La charge CPU en pourcentage ne figure pas sur la liste : un serveur qui tire 100 % parce qu'un encodeur vidéo tourne fait exactement ce qu'on attend de lui. Le débit réseau et le nombre de processus manquent pour la même raison. Les deux aident à chercher une cause, mais ne valent rien comme alerte, car il n'existe aucune valeur à partir de laquelle vous devriez impérativement agir.
La voie de retour, avant que le premier fichier n'existe
Le monitoring est une opération de lecture et ne peut normalement rien casser. Trois choses le peuvent quand même.
Un script qui répare au lieu de signaler. L'idée est séduisante : si nginx est mort, le script n'a qu'à le relancer. Vous obtenez alors un service qui démarre toutes les dix minutes, tourne une demi-seconde et masque la cause. Et un script qui efface de lui-même quand le disque est plein finira par effacer quelque chose dont on avait besoin. La première version se contente de lire et n'appelle ni systemctl restart, ni rm, ni kill.
Les interfaces réseau ouvertes. Les exporteurs de métriques qui écoutent sur toutes les adresses comptent parmi les divulgations de données involontaires les plus fréquentes sur un serveur isolé. Le procédé décrit ici n'ouvre aucun port et ne réclame aucune règle de pare-feu.
La voie d'alerte elle-même. Un monitoring dont la notification n'a jamais été testée n'est pas un monitoring, c'est une impression rassurante. Le test correspondant figure plus bas et n'est pas optionnel.
Comment atteindre le serveur sans SSH
Les serveurs root KVM et les serveurs dédiés n'ont ni IPMI ni iDRAC. L'accès qui reste quand SSH ne répond plus, c'est la console VNC dans l'espace client. Elle ne dépend pas de la pile réseau du système invité, et ni une règle de pare-feu ni un service SSH saturé ne peuvent donc la bloquer. Connectez-vous-y une fois au préalable et assurez-vous de connaître le mot de passe root.
Le coupe-circuit
Si le monitoring devient lui-même le problème, par exemple parce qu'il envoie une alerte par minute, il vous faut deux commandes. Retenez-les avant de commencer :
systemctl disable --now kh-monitor.timer
systemctl mask kh-monitor.service
La première arrête le timer immédiatement et l'empêche de revenir au prochain démarrage. La seconde est le frein d'urgence : un service masqué ne peut plus non plus être lancé à la main par mégarde, ce qui s'annule avec systemctl unmask kh-monitor.service. Si le procédé présente peu de risques, c'est avant tout parce qu'il ne crée que de nouveaux fichiers ; le démontage consiste à supprimer ces fichiers. Gardez malgré tout une seconde session SSH ouverte tant que vous travaillez sur le système.
Vérifier d'abord les indicateurs à la main
Avant qu'un script n'évalue quoi que ce soit, vous devriez avoir vu chaque valeur de vos propres yeux. Sinon, vous ne saurez pas plus tard si une alerte est justifiée ou si votre seuil est absurde.
Espace disque et inodes
df -h
df --output=pcent,target -x tmpfs -x devtmpfs -x squashfs -x overlay
df -i
Les exclusions sont indispensables. Sous Ubuntu 22.04 et 24.04, snap monte ses paquets sous forme d'images squashfs en lecture seule, et celles-ci affichent en permanence 100 %. Sans -x squashfs, votre monitoring signale un disque plein dès la première exécution, tous les jours, pour toujours. Il en va de même pour les points de montage overlay de Docker.
Deux particularités méritent d'être connues. df n'accepte pas -P et --output ensemble et s'interrompt sur un message annonçant des options mutuellement exclusives. Et sur ext4, cinq pour cent sont réservés d'usine à root, ce qui explique que df annonce déjà 100 % alors que root peut encore écrire. La marche à suivre après l'alerte figure dans Disque plein sous Linux.
Le contrôle des inodes n'est pas un sujet secondaire. Un répertoire rempli de millions de minuscules fichiers de session ou de cache peut consommer tous les inodes alors que df -h affiche beaucoup d'espace libre. Les écritures échouent alors sur No space left on device, et l'explication qui vient d'abord à l'esprit est la mauvaise.
RAM
free -m
awk '/^MemAvailable:/ { printf "%d MB\n", $2 / 1024 }' /proc/meminfo
Sur un système Linux en bonne santé, la colonne free est presque toujours petite, parce que le noyau utilise la mémoire inoccupée comme cache de fichiers. Seule available, autrement dit MemAvailable, est fiable : c'est la quantité de mémoire qu'une nouvelle application peut obtenir sans que rien ne parte en swap. Déclenchez vos alertes sur cette valeur, jamais sur free.
Le journal du noyau vous dira si la situation a déjà été tendue par le passé :
journalctl -k -b --grep "Out of memory"
Chaque occurrence trouvée correspond à un processus que le noyau a arrêté faute de mémoire. La façon de réagir sans créer aveuglément du swap est décrite dans Out of Memory et configurer correctement le swap.
Charge système
nproc
cat /proc/loadavg
uptime
Les trois premiers champs de /proc/loadavg sont les moyennes sur une, cinq et quinze minutes. Deux choses sont régulièrement mal comprises. D'abord, sous Linux, la charge n'est pas une grandeur purement CPU : les processus qui attendent des accès disque comptent eux aussi. Une charge de 20 sur quatre cœurs peut signifier que le CPU brûle, ou qu'un support de stockage coince. Ensuite, la valeur sur une minute ne vaut rien pour des alertes, parce que chaque passage de sauvegarde la fait grimper brièvement. Prenez la moyenne sur 15 minutes et fixez le seuil par rapport au nombre de cœurs.
Si votre noyau embarque les statistiques de pression, elles sont plus parlantes, car elles distinguent le CPU, les entrées et sorties ainsi que la mémoire. Elles ne sont pas présentes partout :
test -d /proc/pressure && cat /proc/pressure/io || echo "pas de statistiques de pression dans ce noyau"
Services
systemctl is-system-running
systemctl --failed --no-pager
systemctl is-active nginx
systemctl is-system-running est le contrôle global le plus court qui ait du sens. Il affiche running quand aucune unit n'est en erreur, et degraded dès qu'une seule l'est. Le code de retour vaut en conséquence 0 ou une valeur différente de 0.
Deux pièges. L'état degraded persiste jusqu'à ce que vous le réinitialisiez après réparation avec systemctl reset-failed ; sans cela, une tâche ayant échoué une seule fois maintient le message pendant des semaines. Et pour le contrôle de services isolés, les systèmes de référence divergent : sous Ubuntu 24.04, SSH démarre par activation de socket, ssh.service y reste inactive au repos alors que SSH répond parfaitement. Qui surveille ssh.service à cet endroit récolte une fausse alerte permanente. Sur Ubuntu 24.04, il faut surveiller ssh.socket, tandis que sur Debian 12, Debian 13 et Ubuntu 22.04 c'est ssh.service.
Expiration du certificat
openssl x509 -enddate -noout -in /etc/letsencrypt/live/example.com/fullchain.pem
openssl x509 -checkend 1814400 -noout -in /etc/letsencrypt/live/example.com/fullchain.pem
La seconde commande est la plus intéressante. -checkend attend un nombre de secondes, et 1814400 correspond à 21 jours. Si le certificat expire dans ce délai, la commande affiche Certificate will expire et renvoie le code de retour 1, sinon Certificate will not expire et 0. /etc/letsencrypt/live et /etc/letsencrypt/archive ne sont lisibles que par root.
Ce contrôle a une faille que beaucoup de guides passent sous silence : il vérifie le fichier sur le disque, pas le certificat que votre serveur web délivre réellement. Si le renouvellement aboutit mais que le reload du serveur web échoue, le fichier est neuf et la clé servie est ancienne. Le contrôle du fichier ne signale rien pendant que les visiteurs voient déjà un avertissement de certificat. Seul le regard depuis l'extérieur attrape ce cas :
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -enddate
-servername n'est pas optionnel dès que plusieurs certificats cohabitent sur une même adresse IP. Sans cet ajout, vous obtenez le certificat par défaut du serveur et vous contrôlez le mauvais domaine.
Le script de contrôle
Toutes ces vérifications réunies donnent un script qui ne fait rien d'autre que lire, comparer et signaler en cas d'anomalie. Il lui faut curl et, pour la voie webhook, jq. Sur les installations Debian minimales, les deux manquent :
apt update
apt install -y curl jq
cat > /usr/local/sbin/kh-monitor <<'EOF'
#!/bin/bash
set -u
DISK_WARN="${DISK_WARN:-85}"
INODE_WARN="${INODE_WARN:-85}"
MEM_MIN_MB="${MEM_MIN_MB:-200}"
LOAD_FACTOR="${LOAD_FACTOR:-2}"
CERT_DAYS="${CERT_DAYS:-21}"
UNITS="${UNITS:-ssh nginx}"
STATE_DIR="${STATE_DIRECTORY:-/var/lib/kh-monitor}"
problems=""
add() { problems+="- ${1}"$'\n'; }
notify() {
printf '%s | %s\n' "$1" "$(printf '%s' "$2" | tr '\n' ' ')"
if [ -n "${WEBHOOK_URL:-}" ]; then
printf '%s\n%s' "$1" "$2" | jq -Rs '{text: .}' \
| curl -fsS -m 10 -o /dev/null -H 'Content-Type: application/json' \
--data-binary @- "$WEBHOOK_URL"
fi
if [ -n "${MAILTO:-}" ]; then
printf '%s\n' "$2" | mail -s "$1" "$MAILTO"
fi
}
while read -r pcent target; do
pcent="${pcent%\%}"
case "$pcent" in ''|*[!0-9]*) continue ;; esac
[ "$pcent" -ge "$DISK_WARN" ] && add "Disque ${target} occupé à ${pcent} pour cent"
done < <(df --output=pcent,target -x tmpfs -x devtmpfs -x squashfs -x overlay | tail -n +2)
while read -r ipcent target; do
ipcent="${ipcent%\%}"
case "$ipcent" in ''|*[!0-9]*) continue ;; esac
[ "$ipcent" -ge "$INODE_WARN" ] && add "Inodes occupés à ${ipcent} pour cent sur ${target}"
done < <(df --output=ipcent,target -x tmpfs -x devtmpfs -x squashfs -x overlay | tail -n +2)
mem_avail=$(awk '/^MemAvailable:/ { printf "%d", $2 / 1024 }' /proc/meminfo)
[ "${mem_avail:-0}" -lt "$MEM_MIN_MB" ] && add "seulement ${mem_avail} MB de RAM disponibles"
cores=$(nproc)
load15=$(awk '{ print $3 }' /proc/loadavg)
awk -v l="$load15" -v c="$cores" -v f="$LOAD_FACTOR" 'BEGIN { exit !(l > c * f) }' \
&& add "charge moyenne sur 15 minutes ${load15} pour ${cores} cœurs"
sysstate=$(systemctl is-system-running)
[ "$sysstate" = "running" ] || add "systemd signale l'état ${sysstate}"
for unit in $UNITS; do
systemctl is-active --quiet "$unit" || add "Le service ${unit} est $(systemctl is-active "$unit")"
done
for cert in /etc/letsencrypt/live/*/fullchain.pem; do
[ -r "$cert" ] || continue
openssl x509 -checkend $(( CERT_DAYS * 86400 )) -noout -in "$cert" >/dev/null 2>&1 \
|| add "Le certificat ${cert} expire dans moins de ${CERT_DAYS} jours"
done
mkdir -p "$STATE_DIR"
now=$(printf '%s' "$problems" | sha256sum | cut -d' ' -f1)
before=$(cat "${STATE_DIR}/last" 2>/dev/null || true)
printf '%s' "$now" > "${STATE_DIR}/last"
if [ -z "$problems" ]; then
[ -n "${HEARTBEAT_URL:-}" ] && curl -fsS -m 10 -o /dev/null "$HEARTBEAT_URL"
[ -n "$before" ] && [ "$now" != "$before" ] \
&& notify "Fin d'alerte $(hostname -s)" "Tous les contrôles sont de nouveau sans anomalie."
exit 0
fi
[ "$now" = "$before" ] && exit 0
notify "Alerte $(hostname -s)" "$problems"
EOF
Quatre endroits méritent une explication.
- Les boucles lisent depuis
< <( ... ), pas depuis un pipe. Un pipe déplace la boucle dans un sous-shell, et les messages qui y sont collectés auraient disparu après ledone. Le bug est sournois, car le script se déroule sans erreur et se contente de ne jamais rien signaler. - Les seuils sont lus depuis l'environnement. Vous pouvez redéfinir chaque limite pour un appel isolé. C'est sur ce principe que repose le test d'alerte plus bas.
- L'état est stocké sous forme de somme de contrôle. Une alerte ne part que si la liste des problèmes a changé. Sans cela, un disque plein vous envoie le même message toutes les dix minutes, et vous coupez le monitoring au bout de deux jours.
- La boucle sur les certificats tourne à vide quand aucun répertoire Let's Encrypt n'existe. Le motif reste non développé,
[ -r "$cert" ]échoue, et l'itération est sautée.
Contrôlez maintenant, avant que systemd n'entre en jeu :
chmod 700 /usr/local/sbin/kh-monitor
bash -n /usr/local/sbin/kh-monitor && echo "Syntaxe ok"
/usr/local/sbin/kh-monitor; echo "Code de retour $?"
Sur un serveur en bonne santé, la troisième commande n'affiche rien d'autre que Code de retour 0. Si vous voyez un message, c'est que quelque chose ne va pas, ou qu'un seuil est mal réglé, par exemple parce que UNITS contient un service qui n'existe pas ici.
Le timer systemd
Un cron job ferait aussi l'affaire. Mais un timer offre quatre avantages concrets : il ne lance pas de seconde instance tant que la première tourne, il rattrape après un redémarrage une exécution manquée, sa sortie atterrit dans le journal, et il se coupe d'une seule commande. L'unit de service n'a besoin d'aucune section [Install], puisqu'elle n'est pas activée au démarrage du système mais par le timer.
cat > /etc/systemd/system/kh-monitor.service <<'EOF'
[Unit]
Description=Contrôle rapide de l'état du serveur
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/kh-monitor
EnvironmentFile=-/etc/default/kh-monitor
StateDirectory=kh-monitor
SyslogIdentifier=kh-monitor
Nice=10
IOSchedulingClass=idle
EOF
cat > /etc/systemd/system/kh-monitor.timer <<'EOF'
[Unit]
Description=Exécute kh-monitor régulièrement
[Timer]
OnCalendar=*:0/10
RandomizedDelaySec=60
Persistent=true
[Install]
WantedBy=timers.target
EOF
StateDirectory=kh-monitor crée /var/lib/kh-monitor avec les droits qui conviennent et définit la variable STATE_DIRECTORY à laquelle le script fait appel. Le signe moins placé devant dans EnvironmentFile=-/etc/default/kh-monitor signifie qu'un fichier absent n'est pas une erreur. RandomizedDelaySec=60 disperse l'instant de démarrage, Persistent=true rattrape au démarrage une exécution manquée pendant un arrêt.
Le timer active automatiquement le service du même nom, une ligne Unit= n'est pas nécessaire :
systemd-analyze verify /etc/systemd/system/kh-monitor.service
systemd-analyze calendar '*:0/10'
systemctl daemon-reload
systemctl start kh-monitor.service
systemctl enable --now kh-monitor.timer
Contrôle de réussite :
systemctl list-timers kh-monitor.timer --no-pager
journalctl -u kh-monitor.service -n 20 --no-pager
La liste doit afficher une ligne indiquant la prochaine exécution. Si elle reste vide, le timer n'est pas actif. systemd-analyze calendar repère les fautes de frappe dans l'expression temporelle : il la convertit en forme normalisée et annonce la prochaine échéance. Le détail des fichiers unit et de leurs symptômes d'erreur figure dans Créer un service systemd.
La voie de notification
C'est là que la plupart des monitorings faits maison échouent. Le dispositif d'alerte tourne sur le serveur qu'il surveille, il tombe donc en même temps que lui. Il signale ainsi tout de façon fiable, sauf le seul cas qui compte vraiment.
La réponse s'appelle heartbeat, autrement dit un dispositif d'homme mort : le serveur se signale auprès d'un service distant après chaque exécution réussie, et si le signal n'arrive pas, c'est le service distant qui donne l'alerte. Le script ci-dessus le fait dès que HEARTBEAT_URL est défini. Une panne réseau, un système de fichiers bloqué et un système planté se ressemblent tous vus du service distant, et vous voulez être averti des trois.
Les identifiants ont leur place dans un fichier séparé, pas dans le script. Une adresse de webhook est un secret, car quiconque la détient peut envoyer des messages en votre nom :
cat > /etc/default/kh-monitor <<'EOF'
WEBHOOK_URL=https://exemple.example/hooks/xxxxxxxx
HEARTBEAT_URL=https://exemple.example/heartbeat/xxxxxxxx
UNITS="ssh nginx"
EOF
chmod 600 /etc/default/kh-monitor
Les guillemets autour de UNITS comptent : systemd s'en passerait, mais lors du test plus bas, le fichier est lu par le shell, et là nginx sans guillemets serait pris pour une commande. N'inscrivez que des units qui existent sur ce système, donc ssh.socket plutôt que ssh sur Ubuntu 24.04.
Si vous préférez l'e-mail, il vous faut une voie d'expédition. Un serveur de messagerie complet est surdimensionné, un simple relais suffit :
apt install -y msmtp msmtp-mta bsd-mailx
La configuration se fait dans /etc/msmtprc, avec les identifiants d'une boîte aux lettres existante. Le fichier contient un mot de passe et réclame un chmod 600, faute de quoi msmtp refuse de fonctionner en signalant les droits du fichier. Deux limites qu'il faut dire honnêtement : un e-mail envoyé depuis une adresse IP de serveur fraîchement attribuée atterrit souvent dans les indésirables ou se fait rejeter, et un message que vous ne découvrez qu'au prochain coup d'œil dans votre boîte arrive trop tard en cas de panne. Pour des alertes, la notification push est le choix le plus pratique.
Déclencher l'alerte une fois
Cette étape n'est pas optionnelle. Forcez une alerte en fixant un seuil absurde le temps d'un seul appel :
set -a; . /etc/default/kh-monitor; set +a
DISK_WARN=0 /usr/local/sbin/kh-monitor
rm -f /var/lib/kh-monitor/last
Le message doit maintenant vous parvenir réellement, et pas seulement figurer dans le journal. La troisième ligne efface l'état enregistré, afin que l'alerte de test n'étouffe pas la prochaine exécution réelle. Un effet de bord est voulu : si la remise échoue, kh-monitor.service se termine en erreur et apparaît dans systemctl --failed. Une voie de notification muette serait la pire panne imaginable dans un monitoring.
Le regard depuis l'extérieur
Le heartbeat vous dit que le serveur est vivant. Il ne vous dit pas que votre site web répond. Pour cela, il faut un contrôle depuis un autre emplacement, sur le même modèle de script et de timer, simplement sur un second hôte :
curl -fsS -m 10 -o /dev/null -w '%{http_code} %{time_total}\n' https://example.com/
Quatre points décident de la valeur de ce contrôle. Premièrement : contrôlez le service réel, pas seulement ICMP. Un serveur qui répond au ping alors que le serveur web tourne en boucle infinie passe pour sain lors d'un contrôle par ping. Deuxièmement : -f fait échouer curl sur les codes d'erreur HTTP, sans ce commutateur une page d'erreur compte elle aussi comme un succès. Troisièmement : n'alertez qu'après deux échecs consécutifs, sinon la moindre perturbation réseau passagère signale une panne. Quatrièmement : un appel par minute depuis la même adresse peut tomber dans un rate limit ou être pris pour une attaque par un logiciel de blocage ; inscrivez l'adresse de l'hôte qui contrôle comme exception.
Sans second serveur, il reste un service de contrôle hébergé. Les offres gratuites vérifient le plus souvent toutes les cinq minutes, vous apprenez donc une panne avec le retard correspondant. Pour un serveur isolé, cela suffit, et c'est mieux que l'alternative, qui consiste à ne rien apprendre du tout.
Erreurs fréquentes et solutions
Failed to start kh-monitor.service: Unit kh-monitor.service not found. : après la création ou la modification d'une unit, il manque systemctl daemon-reload. La deuxième cause la plus fréquente est un mauvais répertoire ; les units maison vont dans /etc/systemd/system/.
The unit files have no installation config : vous avez appelé systemctl enable kh-monitor.service au lieu de kh-monitor.timer. Le service n'a délibérément pas de section [Install], c'est le timer que l'on active.
code=exited, status=203/EXEC : systemd n'a pas pu exécuter le fichier. Soit le chemin indiqué dans ExecStart est faux, soit le chmod 700 manque, soit le fichier a été édité sous Windows et porte des fins de ligne avec retour chariot. Le remède est sed -i 's/\r$//' /usr/local/sbin/kh-monitor.
Syntax error: redirection unexpected : le script a été lancé avec sh et non avec bash. Sous Debian et Ubuntu, /bin/sh est le shell dash, qui ne connaît ni < <( ... ) ni += sur les chaînes de caractères. La première ligne doit être #!/bin/bash.
bash: mail: command not found : aucun programme de messagerie n'est installé. Selon le système, la commande mail provient de bsd-mailx ou de mailutils, et les deux diffèrent par leurs commutateurs. Tenez-vous-en à -s pour l'objet.
curl: (22) The requested URL returned error: 404 : l'adresse du webhook est fausse ou a été supprimée côté service distant. Sans -f, curl aurait avalé l'erreur en silence.
curl: (60) SSL certificate problem: certificate has expired : lors du contrôle depuis l'extérieur, ce n'est pas un défaut de l'outil, c'est précisément le constat recherché. Face à votre propre webhook, le même message indique plutôt une heure erronée sur le serveur qui contrôle.
Certificate will expire : sortie normale de openssl x509 -checkend avec le code de retour 1. Vérifiez que le renouvellement fonctionne encore et que le serveur web est bien rechargé ensuite.
Failed to parse calendar specification : l'expression qui suit OnCalendar= est invalide. Testez-la séparément avec systemd-analyze calendar avant de la placer dans l'unit.
Warning: Stopping kh-monitor.service, but it can still be activated by: kh-monitor.timer : vous avez arrêté le service au lieu du timer. Le service ne tourne de toute façon que quelques secondes, c'est le timer qu'il faut couper.
Une alerte à chaque exécution alors que rien n'a changé : l'état n'est pas enregistré. Vérifiez que StateDirectory=kh-monitor figure bien dans l'unit et que /var/lib/kh-monitor/last existe et est accessible en écriture.
Aucune alerte alors que quelque chose est manifestement cassé : déclenchez l'alerte forcée décrite plus haut. Si elle n'arrive pas non plus, le problème vient de la voie de remise, pas des contrôles.
Différences entre les quatre systèmes
| Système | Unit SSH à surveiller | Points de montage squashfs | Où atterrissent les messages |
|---|---|---|---|
| Debian 13 (trixie) | ssh.service, certaines images utilisent ssh.socket | en règle générale aucun | journal uniquement, rsyslog absent des installations minimales |
| Debian 12 (bookworm) | ssh.service | en règle générale aucun | journal, rsyslog selon la variante d'installation |
| Ubuntu 24.04 LTS | ssh.socket | présents la plupart du temps, exclusion nécessaire | journal et rsyslog |
| Ubuntu 22.04 LTS | ssh.service | présents la plupart du temps, exclusion nécessaire | journal et rsyslog |
Ce qui est identique sur les quatre systèmes : systemd-analyze, StateDirectory= et RandomizedDelaySec= sont présents, le script et les fichiers unit fonctionnent sans modification.
Quand la grosse boîte à outils devient rentable
Ce que vous avez maintenant a des limites nettes. Rien n'est historisé, vous ne pouvez donc pas vérifier si la consommation de mémoire monte depuis trois semaines. Aucune corrélation entre plusieurs hôtes n'est possible. Et il n'y a ni escalade, ni règles d'astreinte, ni moyen de mettre en sourdine pour deux heures une alerte déjà connue.
Ce sont précisément ces points qui répondent à la question du changement d'outillage. Une installation à base de métriques et de tableaux de bord devient rentable dès que l'un d'eux s'applique :
- Vous exploitez plus d'une poignée de serveurs et vous voulez les voir côte à côte.
- Vous avez besoin d'historique et de tendances, par exemple pour planifier la capacité ou pour répondre avec des chiffres à une plainte sur la lenteur.
- Plusieurs personnes se partagent l'astreinte, il faut donc des niveaux d'escalade et une mise en sourdine.
- Vous devez prouver la disponibilité auprès de tiers.
Si rien de tout cela ne s'applique, l'installation est le plus souvent une mauvaise affaire pour un serveur isolé. Le collecteur, la base de données, le tableau de bord et les exporteurs occupent facilement, à eux quatre, plusieurs centaines de mégaoctets de RAM sur la machine même dont ils doivent surveiller la mémoire libre. S'y ajoutent un port ouvert de plus et un second logiciel qui réclame des mises à jour. Le point décisif ne change pas : si le collecteur tourne sur le même serveur, il ne signale pas plus la panne de celui-ci qu'un script. Lors du changement, le collecteur a sa place sur un autre hôte, et l'exporteur s'attache à 127.0.0.1 ou se voit restreint par pare-feu à l'adresse de ce dernier.
La voie moyenne fonctionne bien : le timer et le script restent en place, parce qu'ils couvrent le cas de l'alerte, et l'infrastructure de métriques vient en complément quand vous avez besoin d'historiques. Les deux ne s'excluent pas.
Démontage
Si vous voulez vous débarrasser du procédé, cela tient en cinq lignes :
systemctl disable --now kh-monitor.timer
rm -f /etc/systemd/system/kh-monitor.timer /etc/systemd/system/kh-monitor.service
rm -f /usr/local/sbin/kh-monitor /etc/default/kh-monitor
rm -rf /var/lib/kh-monitor
systemctl daemon-reload
Le contrôle final
Six vérifications qui montrent l'état réel et non celui que l'on espère :
systemctl list-timers kh-monitor.timer --no-pagerannonce une prochaine exécution.journalctl -u kh-monitor.service --since "1 hour ago" --no-pagermontre des exécutions à l'intervalle attendu.- Une alerte forcée via
DISK_WARN=0vous parvient réellement, et pas seulement dans le journal. - Après un
reboot, le timer continue de tourner sans que vous ayez à intervenir. - Le heartbeat fait ses preuves : arrêtez le timer et attendez de voir si le service distant donne l'alerte.
systemctl --failed --no-pagerne liste rien, et surtout paskh-monitor.service.
Le point cinq est le plus inconfortable et le plus important. Un monitoring dont le cas d'alerte ne s'est jamais produit reste une supposition. C'est seulement après avoir provoqué la panne volontairement et reçu le message que la chaîne allant du serveur jusqu'à votre téléphone est démontrée complète.
Questions fréquentes
Ai-je vraiment besoin d'un serveur de métriques avec tableau de bord pour un seul serveur root ?
Pourquoi un timer systemd et pas un cron job ?
Mon monitoring signale en permanence un disque plein alors qu'il reste de la place. D'où cela vient-il ?
Comment saurai-je que le serveur est complètement tombé ?
Quelle unit SSH dois-je surveiller ?
Comment éviter de recevoir le même avertissement toutes les dix minutes ?
Le certificat sur le disque est valide, et pourtant les visiteurs voient un avertissement. Comment est-ce possible ?
Comment couper rapidement le monitoring s'il devient gênant ?
2026 KernelHost GmbH. Tous droits réservés. Ce guide est protégé par le droit d'auteur. Sa republication sur d'autres sites web, même partielle ou sous une forme modifiée, n'est pas autorisée sans notre accord écrit. Les citations accompagnées de la source et d'un lien sont expressément les bienvenues.

