Explicateur d’expressions cron
Explique toute expression cron — Vixie, Quartz, EventBridge ou Jenkins —, liste les prochaines exécutions dans n’importe quel fuseau et signale les pièges.
Lue comme Vixie cron.
Ce que cela veut dire
À 00:00 le 13 du mois ou le vendredi
Champ par champ
| Champ | Écrit | Correspond à |
|---|---|---|
| Minute | 0 | 0 |
| Heure | 0 | 0 |
| Jour du mois | 13 | 13 |
| Mois | * | toute valeur |
| Jour de la semaine | 5 | vendredi |
Ce à quoi faire attention
- Les deux champs de jour sont restreints, donc cron exécute ceci dès que l’un des deux correspond : le jour du mois ou le jour de la semaine, pas les deux ensemble. C’est pourquoi 13 avec vendredi signifie le 13 du mois et tous les vendredis, pas vendredi 13.
Prochaines exécutions
Ce que fait cet outil
Il vous relit une expression cron en mots, liste les prochains moments où elle se déclenchera vraiment dans le fuseau horaire où la tâche tourne, et nomme ce que l’expression implique sans le dire. Cette dernière partie est l’essentiel : une expression cron n’est jamais fausse d’une manière qui produise une erreur. Elle tourne les mauvais jours, en silence, jusqu’à ce que quelqu’un s’en aperçoive.
Quatre dialectes sont compris plutôt qu’un seul. La forme à cinq champs que prend crontab, Quartz avec son champ de secondes et ses règles de calendrier, AWS EventBridge avec une année à la fin, et Jenkins avec son hachage. Coller l’un dans un outil qui n’en connaît qu’un autre, c’est ainsi que la plupart des gens découvrent qu’il y en a plusieurs.
Les champs, et combien il y en a
L’expression classique a cinq champs séparés par des espaces, dans un ordre fixe : minute, heure, jour du mois, mois, jour de la semaine. Chacun est une étoile signifiant « chaque », un nombre, une liste séparée par des virgules, une plage avec un tiret, ou un pas avec une barre oblique. Les mois et les jours peuvent s’écrire avec des noms de trois lettres, presque toujours plus clairs que les chiffres.
- Une étoile signifie toute valeur que le champ peut prendre.
- Une plage comme 9-17 signifie toutes les valeurs de 9 à 17 incluses.
- Un pas comme */15 signifie chaque 15e valeur à partir du bas du champ ; 9-17/2 avance à l’intérieur d’une plage, et 5/15 avance de 5 jusqu’au sommet.
- Une liste comme 0,30 signifie exactement ces valeurs.
- Une plage dégénérée comme 13-13 vaut simplement 13 — certaines bibliothèques se trompent et la traitent comme une étoile.
Un sixième champ est l’endroit où les dialectes se séparent. Quartz le met devant et le lit comme des secondes ; EventBridge le met à la fin et le lit comme une année. Six champs nus sont donc réellement ambigus, et cet outil dit dans quel sens il les a lus au lieu de choisir en silence. Envelopper l’expression dans cron(...) — la syntaxe propre à EventBridge — tranche la question.
Les macros sont des raccourcis : @hourly, @daily, @midnight, @weekly, @monthly, @yearly et @annually. Elles se développent en expressions ordinaires, que l’outil affiche. @reboot est l’exception et n’est pas une planification du tout.
Les deux champs de jour, et le « ou » qui ressemble à un « et »
Une date peut se choisir de deux façons — par le jour du mois et par le jour de la semaine — et cron possède les deux champs. Quand les deux sont restreints, la tâche s’exécute dès que l’un des deux correspond. Pas les deux.
Donc 0 0 13 * 5 n’est pas vendredi 13. C’est le 13 de chaque mois, et tous les vendredis : environ 64 jours par an au lieu d’un ou deux. L’expression ressemble à une conjonction et se comporte comme une disjonction, rien ne signale d’erreur, et la tâche tourne simplement plus souvent que prévu.
La règle a une seconde moitié, plus étrange, que presque personne ne connaît. Cron ne teste pas si un champ de jour est restreint ; il teste si le premier caractère du champ est une étoile. Un pas comme */14 compte donc comme une étoile bien qu’il restreigne le champ au 1er, au 15 et au 29 — et sa présence fait repasser les deux champs de jour du « ou » au « et ». Deux expressions qui paraissent également restreintes se comportent alors tout autrement, et cet outil indique quelle règle s’applique.
Quartz et EventBridge évitent toute la question en refusant que les deux champs disent quelque chose : exactement l’un d’eux doit être un point d’interrogation, qui signifie « aucune valeur particulière, c’est l’autre champ qui décide ».
Les pas qui ne divisent pas leur champ
Un pas s’écrit comme s’il s’agissait d’un intervalle, et à l’intérieur d’un cycle du champ c’en est un. Au passage de la limite, en général non.
*/7 dans le champ des heures signifie les heures 0, 7, 14 et 21. Après 21 le champ s’épuise, donc l’exécution suivante a lieu à 0 le lendemain — trois heures plus tard, pas sept. Chaque cycle se termine par un intervalle court, et il en va de même pour */7 en minutes (un trou de quatre minutes après 56) et pour tout autre pas qui ne divise pas sa plage exactement. */15 en minutes et */6 en heures sont sûrs ; la plupart des nombres auxquels on pense ne le sont pas.
Cela compte lorsque le pas est choisi pour étaler du travail. Une tâche en */7 heures ne tourne pas toutes les sept heures, et une limite de débit dimensionnée pour sept sera dépassée une fois par jour.
Les jours de la semaine sont numérotés différemment selon les endroits
Vixie cron numérote les jours de 0 à 7 avec le dimanche aux deux extrémités, si bien que 0 et 7 sont le même jour et que 1 est lundi. Quartz et EventBridge les numérotent de 1 à 7 avec le dimanche à 1, donc là 1 est dimanche et 2 est lundi.
Une expression copiée d’une configuration Quartz vers un crontab s’exécute donc un jour trop tôt, et rien ne proteste nulle part, puisque les deux écritures sont des nombres valides dans les deux systèmes. Les noms de trois lettres — MON, FRI — désignent le même jour partout et constituent la défense simple.
Le changement d’heure : les deux matins de l’année
Un démon cron ne planifie pas des instants. Il regarde l’horloge locale chaque minute et demande si l’expression correspond. Deux fois par an, cette horloge n’est pas une suite bien élevée.
Quand elle saute en avant, une heure de lectures n’arrive jamais. Une tâche réglée sur 02:30 n’a pas de 02:30 ce jour-là. Quand elle recule, une heure de lectures arrive deux fois, et une tâche réglée sur 01:30 en a deux.
Vixie cron distingue ici deux sortes de tâches, et la distinction mérite d’être connue parce qu’elle décide lesquelles des vôtres sont touchées. Une tâche fixée à une heure de pendule — heure et minute fixes — est exécutée exactement une fois dans les deux cas : après un saut en avant elle part immédiatement, et après un retour en arrière cron veille à ne pas la répéter. Une tâche avec une étoile dans l’heure ou la minute est une tâche d’intervalle, et elle suit simplement l’horloge : elle perd une heure d’exécutions au printemps et en répète une à l’automne.
Ainsi une sauvegarde horaire tourne bel et bien deux fois une nuit par an, et une tâche nocturne à 02:30 s’exécute bel et bien à un moment inhabituel une autre nuit. Cet outil confronte les douze prochains mois du fuseau choisi à votre expression et dit lequel des deux cas s’applique, avec la date.
La sortie fiable est de planifier la tâche en UTC, ou en dehors de la plage locale 01:00–03:00, où aucune transition ne tombe.
Sur quelle horloge la tâche se trouve réellement
Un crontab tourne dans le fuseau local de la machine, ou dans celui qu’indiquent CRON_TZ ou TZ en tête de fichier. C’est rarement le fuseau de la personne qui lit l’expression, et c’est pourquoi le fuseau horaire est ici un réglage plutôt que celui de votre navigateur.
Un CronJob Kubernetes est encore autre chose : il lit sa planification en UTC sauf si le manifeste précise un champ timeZone, quoi que dise l’horloge du nœud. Une planification écrite pour des heures de bureau locales et déployée sans ce champ tourne à la mauvaise heure partout hors UTC — et ne change pas avec les saisons, ce qui est un bug ou un soulagement selon la tâche.
Jenkins et le H
Jenkins ajoute un symbole qu’aucun autre dialecte n’a : H, qui ressemble à du hasard et n’en est pas. Jenkins hache le nom de la tâche en une valeur fixe à l’intérieur de la plage du champ, si bien que la tâche tourne à la même heure chaque jour — la sienne — tandis que cent tâches écrites H * * * * s’étalent uniformément sur l’heure au lieu de démarrer toutes à la minute zéro.
Comme la valeur vient du nom de la tâche, et que ce nom ne fait pas partie de l’expression, aucun outil ne peut calculer les heures exactes. Celui-ci résout chaque H au bas de sa plage et le dit : la forme de la planification — à quelle fréquence, quels jours — est exacte, et seul le décalage à l’intérieur de chaque période tient lieu de substitut.
Jenkins redéfinit aussi les macros. Son @daily vaut @midnight, qui n’est pas minuit mais une minute hachée quelque part dans les trois premières heures de la journée.
Ce que cron ne fait pas
- Il ne rattrape pas. Si la machine dormait ou si le démon était arrêté au moment d’une exécution prévue, cette exécution n’a pas lieu plus tard : elle est simplement manquée. anacron existe exactement pour cela et c’est un autre programme.
- Il n’empêche pas les exécutions qui se chevauchent. Si une tâche dure plus longtemps que l’intervalle, la suivante démarre quand même, et au bout d’un moment il y en a plusieurs. Un fichier de verrou est la réponse habituelle.
- Il n’a aucune notion de secondes dans la forme classique. La résolution la plus fine est la minute ; tout ce qui est plus rapide demande Quartz, systemd, ou une boucle dans la tâche elle-même.
- @reboot n’est pas une planification. Il s’exécute une fois au démarrage du démon, il n’a donc pas de prochaine exécution, et sur une machine qui ne redémarre jamais il ne s’exécute jamais.
- Une expression rate dans EventBridge compte à partir de la création de la règle, et ce moment n’est pas dans l’expression : aucun outil ne peut donc dire quand elle se déclenchera.
Questions fréquentes
- Comment lancer une tâche le premier lundi du mois ?
- Pas avec une simple expression cron : cela demande un « et » entre les deux champs de jour, et cron donne un « ou ». Le contournement classique consiste à planifier 0 0 1-7 * * et à laisser la commande tester elle-même le jour de la semaine. Quartz et EventBridge savent l’exprimer directement, sous la forme 0 0 12 ? * MON#1.
- Pourquoi 0 0 13 * 5 tourne-t-il si souvent ?
- Parce que cela veut dire le 13 ou tous les vendredis, pas vendredi 13. Quand les deux champs de jour sont restreints et qu’aucun ne commence par une étoile, cron exécute la tâche dès que l’un des deux correspond. Il n’y a aucun moyen d’écrire un « et » dans le dialecte classique.
- Quelle différence entre */5 et 0-59/5 ?
- Aucune, pour le champ des minutes : les deux donnent 0, 5, 10, etc. La différence apparaît dans les deux champs de jour, où cron tranche entre « et » et « ou » selon que le champ commence ou non par une étoile — */5 et 0-59/5 sélectionnent donc les mêmes jours mais se combinent différemment avec l’autre champ de jour.
- Ma tâche tourne-t-elle deux fois quand l’horloge recule ?
- Si elle a une étoile dans l’heure ou la minute, oui : elle suit l’horloge, et cette heure arrive deux fois. Si elle a une heure et une minute fixes, non — Vixie cron n’exécute une telle tâche qu’une fois. Le panneau de constats dit dans quel cas vous êtes, avec la date concernée.
- Quel fuseau horaire une expression cron utilise-t-elle ?
- Celui de la machine, sauf si CRON_TZ ou TZ sont définis dans le crontab. Un CronJob Kubernetes utilise UTC sauf si le manifeste précise timeZone. Comme le fuseau ne fait pas partie de l’expression, cet outil le demande plutôt que de supposer celui de votre navigateur.
- Puis-je planifier quelque chose toutes les 90 minutes ?
- Pas en une seule expression, car chaque champ boucle indépendamment et 90 minutes ne tiennent pas dans une heure. L’écriture habituelle est en deux expressions, 0 0,3,6,9,12,15,18,21 * * * et 30 1,4,7,10,13,16,19,22 * * *, qui donnent ensemble une exécution toutes les 90 minutes.
- Ce que je colle est-il envoyé à un serveur ?
- Non. L’analyse, l’explication et tout le calcul de la planification tournent dans votre navigateur ; rien n’est téléversé ni journalisé, et cela fonctionne sans connexion réseau.