Aller au contenu principal

Syntaxe des expressions cron

Une expression cron compte cinq champs — minute, heure, jour du mois, mois, jour de la semaine — contenant chacun *, un nombre, une plage comme 1-5, un pas comme */15 ou une liste comme 1,3,5. Tous les champs se croisent, sauf le piège classique : restreignez à la fois jour-du-mois et jour-de-la-semaine, et cron les combine en OU, pas en ET. Le minutage suit l’horloge du serveur.

100 % local
Vous voulez juste l’outil ? Ouvrez Décoder une expression cronLit une planification et montre quand elle se déclencheOuvrir l’outil

Syntaxe des expressions cron en clair

Cron est le planificateur d’Unix depuis les années 1970, et sa grammaire a guère bougé : cinq petits champs qui répondent ensemble à « quand cela s’exécute-t-il ». Vous croiserez la syntaxe dans les crontabs, les systèmes CI, les CronJobs Kubernetes, les plans de maintenance de bases de données et la moitié des planificateurs du web — une syntaxe assez vieille pour voter, toujours gagnante parce qu’elle tient sur une ligne.

La grammaire est simple ; les cas limites ne le sont pas. Chaque champ se croise avec les autres, sauf un, et cette seule exception — jour du mois contre jour de la semaine — fait l’inverse de ce que l’intuition exige. Dimanche répond à la fois à 0 et à 7. Les raccourcis @daily, si commodes, sont des extensions et ne font pas partie du standard. Et il n’existe aucun champ de fuseau horaire dans la syntaxe, donc chaque expression hérite en silence de l’horloge qu’utilise son hôte.

Ce guide parcourt les cinq champs, les opérateurs, le piège des champs de jour, les raccourcis et la réalité des fuseaux horaires, et se termine par la façon de tester une expression avant d’y engager un job de production. Le testeur relié ici s’exécute entièrement dans votre navigateur — l’expression ne quitte jamais l’onglet.

Le moyen le plus rapide d’ancrer ces règles est de les enfreindre exprès et de regarder un analyseur réagir, alors gardez le testeur d’expressions cron ouvert dans l’onglet voisin : il décrit ce que signifie votre expression et liste les prochaines heures d’exécution, calculées localement.

Les planifications modernes vivent généralement dans des fichiers de déploiement plutôt que dans des crontabs ; quand votre expression part dans une définition de pipeline, le guide des bases de YAML couvre les règles d’indentation, de guillemets et de typage que ce fichier respecte.

Les cinq champs

Une expression cron standard compte exactement cinq champs séparés par des espaces, dans un ordre fixe : minute, heure, jour du mois, mois, jour de la semaine. Un job se déclenche quand chaque champ correspond à l’heure courante — les champs sont combinés en ET. Écrivez 30 4 * * * et le job s’exécute à 04:30 chaque jour ; tous les champs doivent concorder pour que l’instant compte.

Chaque champ accepte des nombres dans sa plage, et les champs mois et jour-de-la-semaine acceptent aussi des noms — JAN-DEC et SUN-SAT — que certains planificateurs accueillent sans tenir compte de la casse. Les plages valent qu’on les mémorise, car deux d’entre elles partent d’un endroit inattendu : les mois comptent à partir de 1, et les jours de la semaine à partir de 0. Tout le reste de la syntaxe cron, ce sont des opérateurs posés sur ces champs.

ChampPositionValeurs autoriséesNoms acceptés
Minute1er0-59—
Heure2e0-23—
Jour du mois3e1-31—
Mois4e1-12JAN-DEC
Jour de la semaine5e0-7 (0 et 7 désignent tous deux dimanche)SUN-SAT

Plages, pas et listes

Trois opérateurs font l’essentiel du travail dans les expressions réelles. Une plage, 1-5, correspond à chaque valeur entre ses bornes, incluses. Un pas, écrit après une barre oblique, correspond à la Nième valeur du champ ou de la plage qui le précède — */15 dans le champ des minutes signifie 0, 15, 30, 45, et 9-17/2 dans le champ des heures signifie une heure sur deux de 9 à 17. Une liste, 1,3,5, correspond exactement aux valeurs nommées, et les opérateurs se combinent : 1-5,10 et 0-30/5 sont tous deux légaux.

Deux habitudes gardent les pas corrects. D’abord, */N inclut toujours le minimum du champ — donc */15 touche la minute 0, et voilà pourquoi des flottes de jobs */15 se réveillent tous ensemble en haut de l’heure. Ensuite, un pas sur une plage explicite est souvent plus lisible qu’une liste : 0-59/10 se lit « toutes les dix minutes », ce que 0,10,20,30,40,50 ne fait pas.

ExpressionSe lit comme
0 9 * * 1-509:00, du lundi au vendredi
*/15 * * * *Toutes les 15 minutes
0 0 1 * *Minuit le 1er de chaque mois
30 4 1,15 * SUN04:30 le 1er, le 15 et chaque dimanche
0 22 * * 1-522:00 en semaine

Une expression, testée

30 9 * * 1-5

Ce qu'en dit le testeur

At 09:30, on Monday through Friday.
Next runs (UTC):
  Mon 2026-09-21 09:30
  Tue 2026-09-22 09:30

Le piège jour-du-mois contre jour-de-la-semaine

Chaque paire de champs se croise — sauf jour du mois et jour de la semaine, que cron combine en OU dès que les deux sont restreints. La surprise classique : 0 0 13 * 5 ne signifie pas « vendredi 13 ». Il signifie minuit le 13 du mois, ou minuit n’importe quel vendredi — un job qui s’exécute deux fois certaines semaines et à des dates jamais voulues. Si l’un des deux champs de jour vaut *, le comportement normal en ET revient et seul l’autre compte.

La règle du OU n’est pas un bug ; elle est écrite dans la documentation de POSIX et de Vixie cron, et elle survit parce qu’elle permet aux deux champs de jour de servir des maîtres différents — un job mensuel le 1er peut coexister avec un job hebdomadaire le dimanche dans la même paire de champs. Mais elle défie l’intuition, alors les habitudes défensives sont : ne jamais restreindre les deux sans avoir compté les OU, et quand vous avez vraiment besoin du « vendredi 13 », planifier chaque jour et tester la date dans la commande elle-même.

Dimanche vaut 0 et 7, et les raccourcis sont des extensions

Le jour de la semaine accepte 0 et 7 pour dimanche dans Vixie cron, l’implémentation dont descendent la plupart des systèmes, et 7 est ramené à 0 en entrée. C’est une politesse pour les plages — SUN-SAT peut s’écrire 0-6 ou 1-7 — mais c’est aussi une faille de portabilité : d’autres implémentations rejettent 7 sans appel, et quelques caprices d’analyse rendent 7 risqué dans les listes. Écrire 0 pour dimanche est le choix portable.

Les raccourcis @ — @reboot, @yearly, @annually, @monthly, @weekly, @daily, @midnight et @hourly — sont eux aussi des extensions Vixie, hors de la grammaire POSIX. Ils sont néanmoins pris en charge presque partout où l’on revendique la compatibilité cron, ce qui les rend acceptables en pratique, tout en valant la peine d’être déroulés mentalement : @daily vaut 0 0 * * *, minuit chaque jour, et @reboot signifie une fois au démarrage du daemon, ce qui peut arriver plus tôt ou plus tard que prévu après une replanification.

RaccourciSe développe enSignification
@reboot—Une fois, au démarrage du daemon cron
@yearly / @annually0 0 1 1 *Minuit, le 1er janvier
@monthly0 0 1 * *Minuit le 1er de chaque mois
@weekly0 0 * * 0Minuit chaque dimanche
@daily / @midnight0 0 * * *Minuit chaque jour
@hourly0 * * * *Au début de chaque heure

Le champ de fuseau horaire qui n’existe pas

Cron n’a pas de champ de fuseau horaire. Une expression est évaluée selon l’horloge du daemon — l’heure système locale du serveur — donc le même crontab ne signifie pas les mêmes heures sur des machines de zones différentes, et déplacer un job d’un hôte de Tokyo vers un hôte de Francfort déplace sa planification en silence. Les conteneurs rendent cela plus tranchant : la plupart tournent en UTC quel que soit l’endroit où se trouvent leurs exploitants, si bien que « quand ça tourne » et « quand je le voulais » dérivent d’un décalage que personne n’a annoncé.

L’heure d’été ajoute ses propres dangers dans toute zone en heure locale : un job de 02:30 n’existe pas la nuit du passage à l’heure d’été, et un job de 01:30 s’exécute deux fois la nuit du retour à l’heure d’hiver. Certaines implémentations acceptent des rustines non portables — une ligne TZ ou CRON_TZ dans le crontab, ou un fuseau dans la configuration propre au planificateur — mais la prise en charge varie et la portabilité s’arrête où ces lignes commencent. La pratique honnête est de savoir sur quelle horloge votre expression s’exécute ; le testeur de ce site calcule tout en UTC et le dit à côté de chaque résultat.

Tester une expression avant de la mettre en production

Certaines expressions sont légales et insatisfaisables — 0 0 31 2 * demande le 31 février, et aucune boucle de recherche naïve sur les dates ne le trouve jamais ; voilà pourquoi un vrai testeur borne sa recherche à quelques années et signale une planification qui ne se déclenche jamais au lieu de rester bloqué. D’autres expressions sont légales et simplement pas ce que vous vouliez dire ; le piège du 13-ou-vendredi produit des planifications qui paraissent justes pendant des jours avant de surprendre.

Le flux de travail qui attrape les deux : écrivez l’expression, faites-la reformuler en mots, et regardez les prochaines heures d’exécution concrètes. Une description dit ce qu’un analyseur croit que vous avez écrit ; des horodatages concrets montrent où il se déclenchera réellement. Le testeur de ce site fait les deux — syntaxe standard à cinq champs plus les variantes à six et sept champs façon Quartz — entièrement dans votre navigateur, si bien qu’une expression contenant des noms de jobs internes ou des noms d’hôtes ne quitte jamais l’onglet.

Questions fréquentes

Le testeur cron envoie-t-il mes expressions ou mes noms de jobs ?

Non. L’analyse, la description et le calcul des prochaines exécutions se font tous en JavaScript dans l’onglet de votre navigateur ; l’expression ne quitte jamais votre machine. Vérifiez dans DevTools : ouvrez le panneau Network, évaluez une expression, et regardez la liste des requêtes rester vide. La Content-Security-Policy du site interdit aussi aux scripts de la page d’établir des connexions sortantes.

Pourquoi 0 0 13 * 5 ne signifie-t-il pas vendredi 13 ?

Parce que cron combine en OU les champs de jour quand les deux sont restreints : cette planification se déclenche à minuit le 13 du mois ou n’importe quel vendredi, le premier venu — pas le vendredi 13. C’est un comportement défini, dans POSIX comme dans Vixie cron. Pour attraper la vraie coïncidence, planifiez le job chaque jour et testez la date dans la commande qu’il exécute.

7 est-il une valeur valide pour le jour de la semaine ?

Dans Vixie cron et ses descendants, oui — 0 et 7 désignent tous deux dimanche, avec 7 ramené à 0 en entrée. Mais c’est l’angle le moins portable de la syntaxe : certaines implémentations rejettent 7 sans appel, et il s’y comporte bizarrement dans les listes et les plages. Écrire 0 pour dimanche ne coûte rien et évite entièrement le désaccord.

Dans quel fuseau horaire une expression cron s’exécute-t-elle ?

L’horloge du daemon, quelle qu’elle soit — l’heure système locale du serveur, puisque cron n’a pas de champ de fuseau horaire. Avec des conteneurs, c’est le plus souvent UTC. Certaines implémentations acceptent une ligne TZ ou CRON_TZ dans le crontab, mais c’est non portable, et les zones en heure locale ajoutent des bizarreries d’heure d’été où les jobs de 02:30 sautent une nuit et les jobs de 01:30 tournent deux fois. Connaissez l’horloge avant de faire confiance à la planification.

@daily, @weekly et @reboot font-ils partie du cron standard ?

Ce sont des extensions de Vixie cron plutôt que de POSIX, mais la prise en charge est presque universelle dans ce qui se dit cron. Il vaut la peine de savoir en quoi ils se développent : @daily vaut 0 0 * * *, @weekly vaut 0 0 * * 0, et @reboot se déclenche au démarrage du daemon — ce qui, après une replanification de la machine ou un redémarrage de conteneur, arrive au moment où cela arrive, pas à heure fixe.

Pourquoi mon job ne s’exécute-t-il pas le dernier jour du mois ?

Cron n’a pas de syntaxe pour le « dernier jour » — le champ jour-du-mois s’arrête à 31, et 31 ne correspond que dans sept mois de l’année. La solution de contournement standard est un petit test shell : planifiez à minuit chaque jour et ne lancez que si demain est le 1er. Les planificateurs aux calendriers plus riches (timers systemd, Quartz avec son drapeau L) l’expriment nativement ; POSIX cron, délibérément, ne le fait pas.