Surveillance cron : savoir quand une tâche planifiée échoue en silence
En bref : cron exécute votre tâche et ne dit à personne ce qui s'est passé. Si la tâche échoue, se bloque ou ne démarre jamais, vous l'apprenez par un client, un dossier de sauvegarde vide ou une facture manquante. La surveillance cron inverse la logique : la tâche appelle une URL quand elle se termine, et si cet appel n'arrive pas à l'heure prévue, vous recevez une alerte. C'est ce qu'on appelle le heartbeat monitoring (surveillance par battement de cœur), et cela tient en une ligne dans votre crontab.
Faits vérifiés le 14 octobre 2026 dans la page de manuel de crontab, la documentation Laravel sur la planification des tâches et la documentation GitHub sur les workflows planifiés. Les sources sont listées à la fin.
Pourquoi les tâches cron échouent en silence
Une page web qui ne répond plus est repérée en quelques minutes. Une tâche nocturne qui ne s'exécute plus est repérée le jour où quelqu'un a besoin de ce qu'elle devait produire. Les causes habituelles :
- Un environnement différent. D'après le manuel de crontab, cron ne définit que
SHELL=/bin/sh,LOGNAMEetHOMEpour votre tâche. Tout ce que charge votre shell de connexion — entrées supplémentaires dans lePATH, gestionnaires de versions, variables exportées — est absent. Un script qui fonctionne quand vous le lancez à la main échoue sous cron. - Un signe pourcentage. Dans une ligne de crontab, un
%non échappé devient un saut de ligne, et tout ce qui le suit est envoyé à la commande sur son entrée standard. Undate +%Fdans le nom d'un fichier de sauvegarde casse discrètement toute la ligne. - Une sortie qui ne va nulle part. Cron envoie la sortie d'une tâche par e-mail au propriétaire de la crontab, ou à l'adresse de
MAILTO. Sur la plupart des serveurs, cette boîte n'est jamais lue, ou aucun courrier n'est distribué du tout — le message d'erreur existe donc, mais personne ne le voit. - Une tâche qui ne se termine jamais. Un appel réseau sans timeout, ou un verrou laissé par une exécution qui a planté, et la tâche reste bloquée. Pas d'erreur, pas de sortie, juste rien.
- Le changement d'heure. Le manuel de crontab le dit sans détour : les heures qui n'existent pas pendant le changement ne correspondent jamais, donc ces tâches ne s'exécutent pas, et les heures qui se produisent deux fois font s'exécuter les tâches deux fois.
- La planification disparaît. Une migration de serveur, un conteneur reconstruit ou un nouveau deploy sans la crontab — et la tâche cesse tout simplement d'exister.
- Le planificateur de la plateforme n'est pas une garantie. La documentation de GitHub indique que les workflows planifiés peuvent être retardés en période de forte charge, que certains jobs en file d'attente peuvent être abandonnés et que, dans un dépôt public, ils sont désactivés automatiquement après 60 jours sans activité sur le dépôt.
Aucune de ces situations ne déclenche d'alerte d'elle-même. C'est là le vrai problème de cron : un échec ressemble exactement à un succès — le silence.
Pourquoi la surveillance de disponibilité ne le détecte pas
La surveillance de disponibilité (uptime monitoring) pose une question à votre serveur et vérifie la réponse. Une tâche cron ne répond à aucune question : il n'y a pas de port auquel se connecter ni de page à charger. L'échec à détecter est une absence — une exécution qui aurait dû avoir lieu et n'a pas eu lieu. Seul un système qui attend un signal à un moment donné peut remarquer que ce signal n'est jamais venu.
Comment fonctionne le heartbeat monitoring
Vous indiquez au service de surveillance quand la tâche doit s'exécuter — toutes les 15 minutes, ou selon une expression cron comme 0 3 * * * — et quel retard est acceptable (le délai de grâce, ou grace period). La tâche envoie un ping vers une URL unique chaque fois qu'elle se termine avec succès. Le service sait alors dans quel état se trouve la tâche :
| Situation | État dans le tableau de bord | Alerte |
|---|---|---|
| Le ping est arrivé à l'heure prévue | Saine | — |
| L'heure prévue est passée, mais on est encore dans le délai de grâce | En retard | — (variation normale) |
| Aucun ping à l'heure prévue plus le délai de grâce | Manquée | Oui |
| La tâche a signalé un échec | Manquée | Oui, immédiatement |
| La tâche a signalé son démarrage et ne s'est jamais terminée | Manquée | Oui, après le délai de grâce |
| Le ping réussi suivant arrive | Saine | Notification de rétablissement |
Les deux dernières lignes expliquent pourquoi une bonne configuration envoie plus d'un signal. Un ping à la fin vous dit que la tâche s'est terminée. Un ping supplémentaire au début vous dit qu'elle a commencé — ainsi, une tâche bloquée à mi-chemin est détectée au lieu de ressembler à une tâche qui ne s'est jamais lancée. Et un ping d'échec explicite déclenche l'alerte tout de suite, sans attendre l'échéance.
Ajouter la surveillance à une tâche cron
La version la plus simple n'envoie un ping qu'après une exécution réussie. Le && est important : si la tâche échoue, le ping n'est jamais envoyé et le check passe à l'état « Manquée » à l'échéance.
0 3 * * * /path/to/backup.sh && curl -fsS --retry 3 https://api.alertsleep.com/v1/ping/YOUR-TOKEN
La version complète signale le démarrage, le succès et l'échec :
0 3 * * * curl -fsS --retry 3 https://api.alertsleep.com/v1/ping/YOUR-TOKEN/start; if /path/to/backup.sh; then curl -fsS --retry 3 https://api.alertsleep.com/v1/ping/YOUR-TOKEN; else curl -fsS --retry 3 https://api.alertsleep.com/v1/ping/YOUR-TOKEN/fail; fi
Deux détails sont voulus. Le ping de démarrage est suivi de ; et non de &&, pour que la tâche s'exécute même si le ping ne peut pas être envoyé. Et la ligne utilise if/then/else plutôt que le raccourci répandu job && success || fail, qui signale un échec lorsque la tâche a réussi mais que seul le ping de succès n'est pas arrivé.
Vous pouvez aussi transmettre l'exit code et laisser le service de surveillance trancher. Un code non nul envoyé à l'URL de succès est enregistré comme un échec :
0 3 * * * /path/to/backup.sh; curl -fsS --retry 3 --data "exit_code=$?" https://api.alertsleep.com/v1/ping/YOUR-TOKEN
Les options de curl méritent d'être conservées : -f fait compter une erreur HTTP comme une erreur, -sS reste silencieux sauf en cas de problème, et --retry 3 encaisse une brève coupure réseau.
Planificateur Laravel
Si la tâche est déjà une commande Laravel planifiée, le planificateur peut appeler les URL lui-même — sans échappement shell ni exit codes à transmettre à la main :
// routes/console.php
Schedule::command('backup:run')
->cron('0 3 * * *')
->pingBefore('https://api.alertsleep.com/v1/ping/YOUR-TOKEN/start')
->pingOnSuccess('https://api.alertsleep.com/v1/ping/YOUR-TOKEN')
->pingOnFailure('https://api.alertsleep.com/v1/ping/YOUR-TOKEN/fail');
Un point de plus à surveiller avec Laravel : tout le planificateur repose sur une seule entrée de crontab qui lance php artisan schedule:run chaque minute. Si cette entrée disparaît, toutes les tâches planifiées s'arrêtent d'un coup — et c'est précisément ce que vous signalera un heartbeat sur votre tâche la plus importante.
Workflows planifiés GitHub Actions
Comme les workflows planifiés peuvent être retardés, abandonnés ou désactivés, ils ont autant besoin d'un heartbeat qu'un serveur. Stockez l'URL de ping dans un secret du dépôt, traitez-la comme un mot de passe et ajoutez trois étapes :
on:
schedule:
- cron: '0 3 * * *'
jobs:
nightly:
runs-on: ubuntu-latest
steps:
- run: curl -fsS --retry 3 "${{ secrets.ALERTSLEEP_PING_URL }}/start" || true
- run: ./scripts/nightly.sh
- if: success()
run: curl -fsS --retry 3 "${{ secrets.ALERTSLEEP_PING_URL }}"
- if: failure()
run: curl -fsS --retry 3 "${{ secrets.ALERTSLEEP_PING_URL }}/fail"
Le || true sur le ping de démarrage permet au workflow de continuer si le ping ne peut pas être envoyé. Une exécution que GitHub retarde au-delà de votre délai de grâce, ou qui ne démarre jamais, apparaît comme un heartbeat manqué — le seul échec que le workflow ne peut jamais signaler lui-même.
Quelle durée pour le délai de grâce ?
Assez long pour couvrir la variation normale de la tâche, assez court pour qu'un vrai problème soit encore récent. Une règle utile : prenez l'exécution la plus longue que vous ayez observée et ajoutez une marge. Une sauvegarde qui prend habituellement de 20 à 40 minutes a besoin d'environ une heure ; une tâche de nettoyage qui dure quelques secondes s'en sort très bien avec cinq minutes. Si le check passe régulièrement en retard sans que rien ne cloche, le délai de grâce est trop court — et une alerte qui est le plus souvent une fausse alerte apprend aux gens à l'ignorer.
Comment AlertSleep surveille les tâches cron
Un check cron dans AlertSleep, c'est une planification et une URL de ping :
- la planification est soit une période (d'une minute à 30 jours), soit une expression cron avec son propre fuseau horaire ;
- le délai de grâce peut aller de 30 secondes à 24 heures, cinq minutes par défaut ;
- l'URL de ping accepte GET, POST et HEAD, avec les variantes
/startet/fail, et en option un exit code, une durée et un court message ; - une tâche qui a envoyé
/startet rien d'autre dans le délai de grâce est signalée comme bloquée, et non comme manquée ; - les alertes arrivent par e-mail et dans le tableau de bord quand un check passe à l'état « Manquée », et une notification de rétablissement suit le ping réussi suivant ;
- chaque ping est conservé avec son exit code et sa durée, ce qui vous permet de voir à partir de quand une tâche a commencé à prendre plus de temps ;
- le tableau de bord affiche pour chaque check des extraits crontab et Laravel prêts à coller, et le token peut être régénéré si une URL de ping a fuité.
Tous les détails se trouvent sur la page surveillance des tâches cron. Si vous en êtes encore à écrire la planification elle-même, le Générateur d'expression cron gratuit construit une expression à partir d'un formulaire et liste ses cinq prochaines exécutions.
Une checklist cron en 20 minutes
- Recensez toutes les tâches planifiées.
crontab -lpour chaque utilisateur, les fichiers de/etc/cron.d,systemctl list-timers, les workflows CI planifiés et tout planificateur intégré à votre application. - Pour chacune, demandez-vous ce qui casse si elle ne s'exécute pas pendant une semaine. Sauvegardes, factures, synchronisations de données, renouvellements de certificats et nettoyages arrivent généralement en tête de liste.
- Ajoutez un heartbeat aux tâches importantes — en commençant par les sauvegardes, car une sauvegarde ratée ne se découvre qu'au moment où il faut restaurer.
- Fixez les délais de grâce d'après les durées d'exécution réelles, pas au jugé.
- Testez : arrêtez volontairement une tâche, ou faites-la pointer vers un mauvais chemin, et vérifiez que l'alerte arrive.
- Échappez chaque
%dans vos lignes de crontab et définissez explicitement l'environnement dont la tâche a besoin, en tête du script.
FAQ
Quelle est la différence entre la surveillance cron et la surveillance de disponibilité ?
La surveillance de disponibilité vérifie quelque chose qui est toujours là — un site web, une API, un port. La surveillance cron attend un signal de quelque chose qui ne s'exécute que de temps en temps, et alerte quand ce signal n'arrive pas.
La tâche doit-elle être accessible depuis Internet ?
Non. La tâche se contente d'envoyer une requête HTTPS sortante vers l'URL de ping. Rien n'a besoin de se connecter à votre serveur.
Que se passe-t-il si le ping ne peut pas être envoyé ?
--retry 3 gère les courtes coupures réseau. Si le ping n'arrive toujours pas, le check passe à l'état « Manquée » à l'échéance et vous recevez une alerte. Il peut s'agir parfois d'une fausse alerte, mais c'est l'erreur la moins coûteuse : un vrai échec passé inaperçu coûte bien plus cher qu'un e-mail inutile.
Puis-je surveiller des tâches qui s'exécutent plus d'une fois par minute ?
La période la plus courte est d'une minute. Pour les tâches plus fréquentes, envoyez un ping une fois par minute depuis la tâche, ou surveillez le processus qui les lance.
L'URL de ping est-elle secrète ?
Oui. Quiconque la possède peut déclarer votre tâche en bonne santé. Ne la mettez pas dans des dépôts publics, stockez-la dans un secret de votre CI et régénérez le token si elle fuite un jour.
Sources
Partager cet article
À propos de l'auteur
AlertSleep Team
Monitoring & DevOps
The AlertSleep team helps developers and ops teams keep their services online and communicate outages professionally.