
Les services internes sont souvent considérés « disponibles » uniquement parce qu'ils répondent à un ping. Cette pratique peut sembler insultante pour un technicien support, et pourtant c'est le réflexe que beaucoup gardent sans jamais le remettre en cause. Ce malentendu entre réseau et application coûte cher en alertes manquées, et un petit script Python orienté réseau suffit à le corriger. Pas besoin d'une plateforme de supervision web professionnelle ni de notions avancées : une automatisation pensée pour un débutant, lancée chaque matin avant de décrocher le premier appel, change déjà la donne.
Le ping ne suffit pas pour la supervision web

Au support, le réflexe immédiat face à une panne signalée reste d'ouvrir l'invite de commande et de lancer un ping. Quatre paquets qui reviennent sans perte, et le dossier se referme : le problème viendrait du poste client. Faux.
Sur un réseau d'entreprise, le protocole ICMP qu'utilise la commande ping est très souvent filtré par les pare-feu internes ou les routeurs. Un serveur parfaitement opérationnel peut donc ignorer tous vos pings sans qu'il y ait le moindre problème. L'inverse arrive tout aussi souvent : le système d'une machine virtuelle répond poliment sur le réseau local pendant qu'Apache ou Nginx, en arrière-plan, est totalement figé.
Gwenaël Calvez, mon collègue au helpdesk, ne prend jamais de détour pour signaler une évidence qui m'avait échappé : contrôler un ping pour juger un service web revient à vérifier que la porte d'un immeuble est fermée pour en déduire que l'ascenseur fonctionne. Pour savoir si un service web répond vraiment, il faut lui parler dans sa propre langue, le protocole HTTP ou sa version chiffrée HTTPS, et tester si le port 80 ou le port 443 accepte réellement d'engager un dialogue.
La règle à retenir est simple : tester la couche applicative plutôt que la couche réseau change tout. Plutôt que de subir les appels paniqués des services administratifs, j'ai fini par construire un automatisme léger, sans usine à gaz de supervision ni serveur dédié à configurer deux semaines durant : juste un script qui tourne sur mon poste pendant que la machine démarre le matin.
De urllib à requests : une vérification réseau plus fiable
Côté bibliothèque standard, urllib promettait une solution sans dépendance externe, et c'est ce que suivait le premier tutoriel trouvé en ligne. Dès qu'il a fallu gérer les certificats internes de l'entreprise et intercepter une coupure réseau sans que le terminal n'affiche une trace d'erreur interminable, tout s'est grippé.
Le vrai problème, avant même d'arriver là, c'est que j'avais picoré des tutoriels YouTube sans fil directeur : un bout de script trouvé ici, une astuce glanée là, sans ligne conductrice pour relier le tout. Ça n'a jamais tenu au-delà du premier exercice copié-collé. Reprendre avec la bibliothèque tierce requests a tout changé : en Python, c'est le jour et la nuit, un peu comme passer d'une boîte de vitesses manuelle qui accroche à chaque rapport à une transmission fluide où chaque commande fait ce qu'on attend d'elle.
Techniquement, le squelette du script tient en une poignée d'étapes logiques : on définit une liste d'adresses internes à surveiller, on itère sur chacune avec une boucle simple, on émet une requête requests.get() vers la cible, on lit le code renvoyé par le serveur distant, et on encadre le tout d'un bloc try...except pour intercepter une adresse introuvable ou un câble débranché.
L'objectif reste d'obtenir le fameux statut 200, défini par la RFC 9110 de l'IETF pour signifier que la requête a réussi et que le serveur a transmis le contenu attendu. Un 200 sur le port 443 valide la résolution DNS, la poignée de main TLS et la réception de la page, ce qui vaut déjà bien plus qu'un paquet ping renvoyé dans le vide.
Un code 200 garantit-il qu'un service fonctionne vraiment ?

Deux réalités du réseau d'entreprise sont vite venues heurter mon enthousiasme de débutant.
La première tient à ce qui se passe quand un serveur tombe sans couper sa connexion proprement : sans paramètre explicite, requests.get() attend une réponse indéfiniment. Un script resté bloqué dix minutes sur un intranet sans rien afficher, pendant que le terminal reste immobile faute de paquet de fin, ça suffit à comprendre l'urgence d'ajouter un timeout=5 pour éviter qu'une seule panne ne paralyse tout le contrôle.
Plus instructive encore : un serveur peut répondre 200 OK tout en étant incapable de traiter la moindre transaction métier. C'est arrivé sur le portail de gestion des congés. Le Nginx tournait parfaitement, la réponse arrivait en moins de cinquante millisecondes avec un code irréprochable, sauf qu'à l'écran les utilisateurs voyaient un bandeau rouge d'erreur de connexion à la base de données. Le serveur web était debout, le moteur applicatif derrière, mort.
Un statut 200 garantit seulement que le serveur frontal a généré un document HTML valide, pas que son contenu est utile. Compléter le script en inspectant brièvement le corps de la réponse via response.text, à la recherche d'un mot-clé propre à la page normale comme « Tableau de bord » ou « Bienvenue », évite de crier victoire trop vite.
Garder le script simple, sans fioritures inutiles
Voici la structure à laquelle je suis arrivé pour mes vérifications du matin. Pas de classes compliquées ni de programmation asynchrone quand on débute : l'essentiel tient dans un script lisible qui ne cache rien de ce qu'il fait.
import requests
SERVEURS = [
{"nom": "Intranet Principal", "url": "https://intranet.local.lan", "mot_cle": "Bienvenue"},
{"nom": "Serveur Comptabilite", "url": "http://compta.local.lan:80", "mot_cle": "Connexion"},
{"nom": "Documentation Technique", "url": "https://wiki.local.lan:443", "mot_cle": "Documentation"}
]
def verifier_services():
for service in SERVEURS:
nom = service["nom"]
url = service["url"]
mot_cle = service["mot_cle"]
try:
reponse = requests.get(url, timeout=4)
if reponse.status_code == 200:
if mot_cle in reponse.text:
print(f"[OK] {nom} est joignable et fonctionnel.")
else:
print(f"[ALERTE] {nom} repond 200 mais le mot-cle est absent (panne applicative probable).")
else:
print(f"[ERREUR] {nom} retourne un code HTTP {reponse.status_code}.")
except requests.exceptions.Timeout:
print(f"[DELAI] {nom} ne repond pas (timeout depasse).")
except requests.exceptions.ConnectionError:
print(f"[ECHEC] Impossible de joindre {nom} (reseau ou service coupe).")
except Exception as e:
print(f"[INCONNU] Erreur imprévue sur {nom} : {e}")
if __name__ == "__main__":
verifier_services()
Dans mon coin de travail improvisé, au salon de l'appartement à Cesson-Sévigné, les deux écrans côte à côte affichent enfin une colonne de 200 OK qui défile sans planter, et c'est une satisfaction discrète qu'aucun cours théorique n'enseigne. Le petit Raspberry Pi posé dans un coin du bureau, qui me sert de serveur maison, a été le premier cobaye avant que je ne pointe le script vers les vraies applications du bureau. Trois secondes de script, et je sais où je mets les pieds avant de décrocher le premier combiné téléphonique de la journée.
Les leçons réseau derrière ce petit script

Ce projet de quelques dizaines de lignes a fait progresser ma compréhension du réseau plus que des chapitres entiers de manuels. Gérer soi-même les erreurs dans le terminal force à visualiser le chemin que parcourt un paquet d'un bout à l'autre de l'infrastructure.
Une erreur de connexion refusée m'a appris à lire une adresse IP comme une adresse postale ordinaire : un numéro qui existe bel et bien, une porte qui ne s'ouvre à personne parce qu'aucun service n'écoute derrière. Quand l'erreur concerne plutôt une résolution de nom qui échoue, c'est le serveur DNS interne qui a un souci, pas le service web en lui-même.
Apprendre à distinguer ces erreurs dans son propre script fait gagner un temps précieux lors du dépannage quotidien des postes. On visualise mieux comment les paquets transitent entre les sous-réseaux, un peu comme en se penchant sur la façon dont les routeurs traitent les adresses privées en découvrant comment comprendre le fonctionnement du NAT et du PAT pour le support.
Au-delà du simple contrôle, j'ai programmé l'exécution de ce script chaque matin via le planificateur de tâches, associé à une routine déjà en place pour organiser ses fichiers de sauvegarde automatiquement avec un script Python. Un fichier texte daté, généré sur le bureau, résume l'état du parc applicatif pendant que je pose ma tasse de café, sans tableau de bord tape-à-l'œil.
Ce contrôle reste volontairement limité au service web : vérifier les codes de réponse HTTP et les temps de réponse d'une liste de serveurs avec un script court. Une alerte de panne réseau complète, avec notification immédiate dès qu'un lien tombe, reste un autre sujet, traité ailleurs en détail.
Pour les ralentissements plus sournois, ceux où un serveur répond par intermittence avec des temps de réponse aberrants sans jamais tomber complètement, j'avais aussi creusé comment identifier les erreurs de duplex réseau grâce à une formation Cisco, un souci matériel vicieux qui fait échouer des requêtes web sans couper le lien physique.
Si les exercices de cours vous semblent trop éloignés de votre quotidien de technicien support, laissez tomber les calculatrices en ligne de commande et les jeux de devinettes de nombres. Prenez un vrai irritant : trois URL vérifiées à la main chaque jour, un dossier partagé qui s'engorge, une imprimante muette. Vingt lignes de script écrites pour régler son propre problème valent largement n'importe quel module regardé passivement sur un écran.