Cron-Ping

Cron toutes les 5 minutes : la ligne */5 qui tient en prod

Dernière mise à jour : juillet 2026 · Yohann Kipfer — je développe et j'exploite Cron-Ping.

Réponse directe

*/5 * * * * lance une tâche toutes les 5 minutes. 288 fois par jour, à :00, :05, :10, etc. Pour qu'un cron appelle une URL, voici la ligne à utiliser :

*/5 * * * * curl -fsS --max-time 10 --retry 3 -o /dev/null https://example.com/cron

Pas */5 * * * * curl https://example.com/cron. C'est la version que tous les tutos recopient, et elle vous ment : curl sort en code 0 sur un HTTP 500, donc un endpoint cassé ressemble trait pour trait à un endpoint qui marche. Chaque flag ci-dessous est là parce que quelque chose a pété sans lui.

D'abord : c'est laquelle, votre question ?

« Cron qui ping une URL », ça veut dire trois choses différentes. Les articles du top 10 en choisissent une et font comme si les deux autres n'existaient pas — d'où les gens qui repartent avec la mauvaise ligne. Prenez la vôtre :

1

Vous voulez que cron APPELLE une URL.

Déclencher un endpoint, reconstruire un cache, garder une instance gratuite éveillée. L'URL, c'est le travail. Continuez : c'est la ligne du dessus, et les flags comptent plus qu'on ne croit.

2

Vous voulez SAVOIR que votre cron a bien tourné.

L'URL n'est pas le travail, c'est le témoin. C'est l'absence d'appel qui déclenche l'alerte. Ça s'appelle un dead man's switch, et c'est la seule des trois que cron ne sait pas faire tout seul.

Aller au pattern heartbeat
3

Vous n'avez pas de serveur du tout.

Pas de machine, pas de crontab, rien sur quoi taper crontab -e. Alors ce n'est pas cron qu'il vous faut, c'est un cron-as-a-service. cron-job.org est gratuit et fait le boulot. Revenez au point 2 une fois que ça tourne : les schedulers hébergés se taisent aussi.

cron-job.org (gratuit)

Ce que dit vraiment */5 * * * *

Cinq champs séparés par des espaces, lus de gauche à droite. L'étoile veut dire « chaque ».

Les cinq champs crontab de */5 * * * *
ChampValeurSe lit
minute*/5toutes les 5 minutes de l'heure : 0, 5, 10 … 55
heure*toutes les heures
jour du mois*tous les jours
mois*tous les mois
jour de la semaine*tous les jours de la semaine

*/5 veut dire « toutes les 5 minutes comptées à partir de 0 », pas « 5 minutes après la fin du run précédent ». Si vous lancez le script à la main à 14h03, le prochain run cron reste 14h05. Deux minutes plus tard, pas cinq. C'est cron qui tient l'horloge, pas votre job.

Ça explique aussi un piège : */7 donne :00, :07 … :56, puis l'heure change et le run suivant tombe à :00, un écart de 4 minutes au lieu de 7. Un pas ne se répartit proprement que s'il divise 60. Valeurs sûres : 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30. D'où le 5 partout.

Le sixième champ qui bouffe un après-midi

# ~/crontab, édité avec 'crontab -e' — CINQ champs
*/5 * * * * /opt/job.sh

# /etc/cron.d/monjob ou /etc/crontab — SIX champs, il y a une colonne user
*/5 * * * * root /opt/job.sh

Collez la version à cinq champs dans /etc/cron.d/ et cron lit /opt/job.sh comme un nom d'utilisateur. Deux autres règles pour ce dossier, muettes toutes les deux quand elles cassent : le nom de fichier ne peut contenir que lettres, chiffres, underscores et tirets (monjob.sh est ignoré, monjob est lu), et il faut un saut de ligne final sinon la dernière ligne saute.

Générez votre ligne

Choisissez une fréquence, dites ce qui tourne, cochez ce qu'il vous faut. La sortie est la ligne à coller dans crontab — % échappés, timeout borné, codes de sortie honnêtes.

Ce que cron lance
Votre ligne crontab
*/5 * * * * curl -fsS --max-time 10 --retry 3 -o /dev/null https://example.com/cron/refresh-cache
5 prochaines exécutions

Les flags curl, un par un

C'est la partie que les tutos sautent. Un curl https://url nu dans un crontab, ce n'est pas une ligne de monitoring, c'est une rumeur.

Les flags curl d'une ligne cron, et ce qui casse sans eux
FlagCe qu'il faitSans lui
-f, --failSort en 22 sur un HTTP 400+ au lieu de 0Un 500 sort en 0. Votre chaîne && s'exécute comme si tout allait bien. C'est l'échec silencieux n°1 de toute cette page.
-s, --silentPas de barre de progressionCron vous maile une barre de progression. 288 fois par jour.
-S, --show-errorGarde le message d'erreur sur stderr malgré -s-s tout seul avale aussi la raison. Vous récupérez un échec sans explication.
--max-time 10Plafond dur sur une tentativecurl reste pendu sur une connexion TCP à moitié morte jusqu'à ce que le noyau lâche — des minutes. Sur un cycle de 5 min, les runs s'empilent.
--retry 3Réessaie sur erreur transitoire et 5xxUn hoquet DNS = un run manqué = une fausse alerte.
-o /dev/nullJette le corps de la réponseLe corps finit dans le mail de cron, ou dans votre fichier de log. Toutes les 5 minutes.

Une réserve sur la combinaison : --max-time borne une tentative, --retry en ajoute d'autres, et curl dort entre chaque (1s, puis 2s, puis 4s). Donc --max-time 10 --retry 3 n'est pas un budget de 10 secondes — tablez plutôt sur 45 secondes dans le pire cas. Ça passe sur un cycle de 5 minutes. Pas sur un cycle d'une minute : ajoutez --retry-max-time 20 et arrêtez de deviner.

Le % qui détruit votre ligne en silence

Une phrase dans man 5 crontab, facile à rater, et elle coûte un après-midi à qui la rate : dans une commande crontab, un % non échappé devient un saut de ligne, et tout ce qui suit le premier est envoyé à la commande sur stdin.

A l'air juste, ne fait rien

*/5 * * * * curl -fsS -d "jour=$(date +%F)" https://example.com/hook

Ça ne poste pas jour=2026-07-16. Cron exécute curl -fsS -d "jour=$(date + et lui envoie F)" https://example.com/hook en entrée standard. Aucune erreur de syntaxe, aucun mail, aucune ligne de log. Ça fait juste la mauvaise chose, tranquillement, pour toujours.

Échappez-les tous

*/5 * * * * curl -fsS -d "jour=$(date +\%F)" https://example.com/hook

Ça mord sur date +%F, date +%Y-%m-%d, toute URL contenant %20 ou %2F, et chaque format printf. C'est aussi la vraie réponse à « la commande marche quand je la colle dans mon shell mais pas dans cron » : votre shell ne fait pas ça, seul crontab le fait. Le générateur plus haut les échappe et vous le dit.

Son cousin : le & dans une query string

Même famille de bug, une couche plus bas. Cron passe votre commande à /bin/sh, donc un & non quoté veut dire « mets tout ce qui précède en arrière-plan et continue » :

# curl part en arrière-plan sur .../hook?a=1 — et &b=2 est jeté
*/5 * * * * curl -fsS https://example.com/hook?a=1&b=2

# les guillemets doubles règlent ça (les simples tueraient aussi $(date …))
*/5 * * * * curl -fsS "https://example.com/hook?a=1&b=2"

Aucune erreur non plus, évidemment. Vous récupérez un 200 sur la moitié de l'URL que vous vouliez. Guillemets doubles et pas simples, pour que $(date +\%F) continue de s'évaluer — c'est pour ça que le générateur plus haut quote avec " dès qu'il repère un &.

288 runs par jour, et cron se fiche que le précédent soit fini

À 5 minutes d'écart, chaque run dispose de 300 secondes avant le suivant. La plupart du temps votre job en prend 3. Puis une API en amont ralentit, un run prend 6 minutes, et cron lance le suivant quand même. Deux se chevauchent. Puis trois. Puis la machine swappe et tous les runs ralentissent, ce qui en fait chevaucher davantage — c'est un empilement, et ça ne se répare pas tout seul. Un script de backup qui fait ça sur une base en production, c'est comme ça qu'on obtient un dump irrécupérable à 4h du matin.

Cron n'a aucun contrôle de concurrence. Aucun. Ajoutez-le vous-même :

*/5 * * * * /usr/bin/flock -n /var/lock/monjob.lock /opt/monjob.sh

-n veut dire : si le verrou est déjà pris, sors tout de suite (code 1) au lieu d'attendre. C'est ce qu'on veut — un run sauté est un fait mesurable, une file d'attente est un incendie. Enlevez le -n et flock attend poliment, ce qui déplace l'empilement dans une file et repousse le crash.

Chemin absolu, volontairement. Cron vous donne un PATH à /usr/bin:/bin et rien d'autre. Pas de .bashrc, pas de .profile, rien de l'environnement dans lequel vous avez testé. flock habite dans /usr/bin, donc il passe, mais le script qu'il enrobe appelle probablement node, php ou aws, et ceux-là non.

À quelle fréquence le faire tourner ?

Les runs s'additionnent plus vite qu'on ne l'imagine. Ce sont les deux dernières colonnes qui comptent.

Intervalles cron : expression, volume de runs et délai de grâce à régler sur un heartbeat
IntervalleExpressionPar heurePar jourSur 30 joursGrâce à régler
Chaque minute *601 44043 2003 min
Toutes les 5 minutes/5 *122888 64010 min
Toutes les 10 minutes/10 *61444 32020 min
Toutes les 15 minutes/15 *4962 88025 min
Toutes les 30 minutes/30 *2481 44045 min

La colonne « grâce », c'est le délai avant que « pas encore de ping » devienne « alerte ». Règle du pouce : deux fois l'intervalle, ou l'intervalle plus votre pire temps d'exécution observé, le plus grand des deux. Réglez-la pile sur l'intervalle et un micro-coup de mou réseau de 4 secondes vous réveille à 3h. Vous couperez cette alerte en une semaine, et vous voilà revenu à zéro monitoring avec des étapes en plus. Le plan gratuit de Cron-Ping refuse de descendre sous 60 secondes de grâce. C'est volontaire, exactement pour cette raison.

Et si vous pinguez l'API de quelqu'un d'autre : */5, c'est 8 640 requêtes par mois depuis une seule machine. Les offres gratuites le remarquent. Les rate limiters aussi.

Cron ne vous dira jamais qu'il n'a pas tourné

Il n'existe aucun événement « run manqué ». Si crond est arrêté, si un passage d'Ansible a écrasé la crontab, si le disque est plein et que le shell ne peut plus forker, si quelqu'un a tapé crontab -r — le résultat observable est identique à celui d'un système sain et calme. Le silence. C'est tout le problème, et c'est pourquoi « regarde les logs » n'est pas une réponse : cron logge qu'il a démarré une commande. Il ne logge pas le code de sortie, et il ne logge rigoureusement rien quand il n'a jamais démarré.

Ce que cron a, en revanche, c'est le mail. Mettez MAILTO=vous@example.com en tête de crontab et chaque run qui écrit sur stdout ou stderr vous envoie un mail. À 288 runs par jour, ça fait 288 mails. Vous les filtrerez dans un dossier en deux jours et vous arrêterez d'ouvrir le dossier en deux semaines. Le mail n'est pas du monitoring. C'est du monitoring qu'on vous apprend à ignorer.

Les codes de sortie, eux, valent le détour :

*/5 * * * * /opt/job.sh && echo "ok" || echo "job.sh a rendu $?" >&2

&& part sur un code 0, || sur tout le reste. Et c'est précisément pour ça que l'absence de -f sur curl est vicieuse : sans lui, un HTTP 500 vaut « code 0 », et votre branche de succès annonce joyeusement un succès.

L'autre lecture : pinger une URL pour prouver que le cron a tourné

Renversez le sens. Au lieu que cron appelle votre app, cron appelle une URL dont le seul métier est de remarquer que l'appel n'arrive plus. C'est l'absence qui fait signal. Un dead man's switch.

*/5 * * * * /opt/job.sh && curl -fsS --max-time 10 -o /dev/null https://cron-ping.com/p/VOTRE-TOKEN

Lisez de gauche à droite : le job tourne, sort en 0, curl part, le check est marqué vivant. Le job plante → pas de code 0 → pas de curl → pas de ping → passé le délai de grâce, on vous mail ou on vous Slack. La machine perd le courant → pas de ping non plus. C'est là tout l'intérêt : ça attrape les pannes qu'aucun log sur cette machine ne pouvait attraper, puisque c'est la machine qui est tombée.

Ajoutez la branche d'échec pour que « planté » et « jamais démarré » cessent de se ressembler :

*/5 * * * * /opt/job.sh \
  && curl -fsS --max-time 10 -o /dev/null https://cron-ping.com/p/VOTRE-TOKEN \
  || curl -fsS --max-time 10 -o /dev/null https://cron-ping.com/p/VOTRE-TOKEN/fail

Il y a aussi /p/VOTRE-TOKEN/start, appelé avant le job, si vous voulez mesurer la durée plutôt que la deviner.

La limite honnête

Ça vous dit que le job est sorti en 0. Ça ne vous dit pas que le backup qu'il a écrit est restaurable. Un script qui sort en 0 sur un dump vide pingue au vert indéfiniment, et vous le découvrirez la pire semaine possible. Faites vérifier son propre travail au script — le dump fait plus de 1 Ko, le nombre de lignes est cohérent — et là, le ping veut dire quelque chose. Un heartbeat n'est jamais plus honnête que le code de sortie derrière.

Toutes les 5 minutes ailleurs que sur un Linux

Même intention, autres pièges. La troisième colonne, c'est ce que les docs enterrent.

Lancer un job toutes les 5 minutes selon la plateforme, et le piège de chacune
PlateformeToutes les 5 minutesLe piège
crontab Linux (Vixie / cronie)/5 *La minute est le plancher. Aucun contrôle de concurrence, aucune notification de run manqué, aucun code de sortie dans les logs.
Timer systemdOnCalendar=*:0/5Persistent=true rejoue un run manqué au boot — parfait sur un portable, surprenant sur un serveur resté éteint une journée. RandomizedDelaySec étale la charge mais floute l'horaire : élargissez la grâce en conséquence.
GitHub Actions- cron: '/5 *'5 minutes est le plancher documenté. Les runs sont mis en file sous charge — GitHub cite le début de chaque heure — et abandonnés plutôt que reportés. Et un workflow planifié est désactivé après 60 jours sans activité sur le dépôt. En silence.
Vercel Cron"schedule": "/5 *"En Hobby, les cron jobs sont déclenchés une fois par jour quoi que vous écriviez dans l'expression. Le pas à la minute demande le plan Pro. L'expression ne renvoie pas d'erreur — elle ne veut simplement pas dire ce qu'elle dit.
CronJob Kubernetesschedule: "/5 *"Le concurrencyPolicy: Allow par défaut laisse les runs se chevaucher — mettez Forbid. Et si le contrôleur rate plus de 100 démarrages prévus, il arrête de planifier et logge « too many missed start times » au lieu de rattraper.
Dockerpas de cron dans l'imageSoit un cron -f en PID 1 dans son propre conteneur, soit la crontab de l'hôte qui fait docker exec. Cron dans un conteneur n'a pas de MTA : stderr ne va nulle part du tout — le filet de sécurité du mail, que vous n'aimiez pas, a disparu aussi.
cPanel / mutualiséles mêmes cinq champs, dans un formulaireBeaucoup d'hébergeurs vous plafonnent discrètement à 5 ou 15 minutes. Et le binaire PHP est rarement php. C'est plutôt /usr/local/bin/ea-php82. Faites which php en SSH avant d'ouvrir un ticket.
Windows Task Schedulerpas de syntaxe cronDéclencheur → répéter la tâche toutes les 5 minutes pendant 1 jour. Et cochez « Exécuter même si l'utilisateur n'est pas connecté », sinon rien ne tourne sur une machine sans session.
Render / Railway / Fly.iosyntaxe cron, managéChaque run démarre un conteneur. 288 démarrages à froid par jour, ce sont 288 démarrages facturés par jour — regardez le coût avant de choisir 5 minutes par habitude.

Fuseau horaire et heure d'été

Cron tourne dans le fuseau du serveur, qui est très souvent UTC et presque jamais celui que vous avez en tête. Vérifiez avec timedatectl avant de discuter. Ensuite, soit vous acceptez UTC — c'est honnêtement le choix le plus simple —, soit vous le fixez en tête de crontab :

CRON_TZ=Europe/Paris
*/5 * * * * /opt/job.sh

CRON_TZ= marche sur Vixie cron et cronie, donc Debian, Ubuntu, RHEL et compagnie. Ce n'est pas du POSIX. Une crontab busybox dans un conteneur Alpine ignore la ligne et continue gaiement en UTC — sans avertissement, évidemment. Testez, ne supposez pas.

L'heure d'été, précisément — parce que le conseil habituel est faux une fois sur deux

Un job en */5 a une heure en joker : il suit donc l'horloge murale. Rien de sauté, rien de doublé, le changement d'heure est un non-événement. Les jobs qui font mal sont ceux à heure fixe. Prenez 30 2 * * * la nuit du passage à l'heure d'été : 2h30 n'existe pas, et le cron de Debian le lance peu après le saut. La nuit du retour à l'heure d'hiver, 2h30 arrive deux fois, et cron ne le lance qu'une. Donc votre heartbeat de 5 minutes va bien, et c'est votre backup de 2h30 qui mérite un second regard. Cette distinction est dans man 8 cron et à peu près nulle part ailleurs.

Le tester sans attendre 5 minutes

Personne ne devrait déboguer une ligne cron en regardant une horloge. La boucle dure 20 secondes :

  1. crontab -e ouvre votre crontab utilisateur. Si vi vous saute dessus : EDITOR=nano crontab -e. À la sauvegarde, vous devez voir crontab: installing new crontab. Pas de message = rien n'a été installé.
  2. Ne déboguez pas à travers cron. Lancez d'abord la commande exacte à la main, en retirant les échappements \% — si ça échoue là, cron n'a jamais été le problème.
  3. Ensuite, reproduisez l'environnement de cron, parce que c'est là que se planquent les 90 % restants. Cron vous donne un PATH nu et rien de votre configuration shell.
  4. Seulement là, remettez la ligne dans la crontab. Si vous voulez vraiment voir un vrai run cron, mettez le champ minute à deux minutes d'ici pour un coup, puis remettez-le.
# Ce que cron donne réellement à votre script — le coupable habituel
env -i /bin/sh -c '/opt/job.sh'

# Faire cracher le vrai environnement de cron une fois, puis le lire
*/5 * * * * env > /tmp/cron-env.txt

Avant tout ça : crontab -l > ~/crontab.bak. crontab -r supprime toute votre crontab sans demander confirmation, et sur un clavier le r est collé au e. Ne me demandez pas comment je le sais.

Où sont les logs

Où cron écrit ses logs, par système
SystèmeCommande
Debian / Ubuntujournalctl -u cron -f — ou grep CRON /var/log/syslog
RHEL / Rocky / Almajournalctl -u crond -f — ou /var/log/cron
Alpine (busybox)/var/log/messages — et crond a besoin de -L /var/log/cron.log pour logger tout court
macOSlog show --predicate 'process == "cron"' --last 1h

Lisez ces lignes attentivement : cron logge qu'il a démarré la commande. Il n'y a aucun code de sortie là-dedans. Un job qui démarre et meurt une seconde plus tard est indiscernable d'un job qui démarre et fonctionne.

FAQ

Quelle est l'expression cron pour toutes les 5 minutes ?

*/5 * * * *. Elle s'exécute aux minutes 0, 5, 10, 15 … 55 de chaque heure, tous les jours — 288 runs par jour. Les cinq champs sont minute, heure, jour du mois, mois, jour de la semaine, et */5 dans le premier veut dire « toutes les 5 minutes comptées à partir de 0 ».

Comment faire un cron qui ping une URL ?

*/5 * * * * curl -fsS --max-time 10 --retry 3 -o /dev/null https://example.com/cron. Le -f n'est pas optionnel : sans lui, curl sort en 0 sur un HTTP 500 et votre job annonce un succès sur un endpoint cassé. --max-time doit rester bien en dessous de votre intervalle.

Cron peut-il tourner toutes les 5 secondes ?

Non. La minute est le plancher de cron, par conception — il n'y a pas de champ secondes. Utilisez un timer systemd avec OnUnitActiveSec=5s, ou un processus long supervisé avec une boucle de sleep. À 5 secondes, cron est le mauvais outil, et bricoler des sleep 5 dans une ligne crontab est pire.

Pourquoi mon cron marche dans le terminal mais pas dans cron ?

Trois causes, par fréquence : le PATH de cron se limite à /usr/bin:/bin et il ne lit jamais votre .bashrc ; vous avez mis un chemin relatif alors que le répertoire de travail de cron n'est pas le vôtre ; ou il y a un % non échappé dans la ligne, que cron transforme en saut de ligne. Testez avec env -i /bin/sh -c 'votre-commande'.

*/5 est-il équivalent à 0,5,10,15,20,25,30,35,40,45,50,55 ?

Mêmes exécutions, oui. */5 est une extension de Vixie cron plutôt que du POSIX : un cron strictement POSIX — de vieux Solaris et AIX — ne comprend que la liste. Sur Linux, macOS et busybox, */5 marche et se lit plus vite.

Comment savoir si mon cron a réellement tourné ?

Cron ne vous le dira pas : il n'a pas d'événement « run manqué », et ses logs enregistrent des démarrages, pas des codes de sortie. Soit vous greppez la ligne de démarrage à chaque fois, soit le job ping une URL en cas de succès et un service vous alerte quand le ping n'arrive pas dans le délai de grâce.

Envie de savoir quand cette ligne s'arrête ?

C'est tout le produit. Une URL à curler en fin de job, un mail ou un message Slack quand le ping n'arrive pas. 10 checks gratuits, sans carte, hébergé en Europe.

Créer un check gratuit

Plan gratuit : 10 checks, alertes email, historique 7 jours. Le Pro est à 9 €/mois si vous le dépassez.

Guides liés

Surveiller un cron Linux qui ne tourne plusLe versant diagnostic : vérifier crond, lire le mail, repérer une crontab écrasée.Surveiller un workflow GitHub Actions planifiéLa désactivation automatique à 60 jours, et pourquoi une liste de workflows verte ne prouve rien.Surveiller un Vercel Cron JobLe plafond « une fois par jour » du plan Hobby, les timeouts, et le 500 qui compte quand même comme « invoqué ».Documentation Cron-PingPings de succès, de start et de fail, capture des logs, exemples curl/wget/Python.Une alternative européenne à Healthchecks.ioCe qu'on fait différemment, et quand Healthchecks.io auto-hébergé est le meilleur choix.

Sources