Aller au contenu
Toova
Tous les outils

Syntaxe des expressions cron expliquée

Toova

Les expressions cron font partie de ces sujets qu'un développeur apprend une fois, oublie dans les détails, puis recherche à nouveau tous les six mois. Une chaîne de cinq caractères comme 30 9 * * 1-5 peut encoder un planning étonnamment précis — « chaque jour ouvré à 9h30 » — mais la syntaxe recèle suffisamment de cas particuliers pour prêter à confusion : champs indexés à 0 ou à 1, dimanche valant à la fois 0 et 7, différence entre le standard Unix et l'extension à six champs de Quartz, et comportement subtil des valeurs de pas combinées avec des plages.

Ce guide couvre la syntaxe cron depuis les premiers principes, puis passe en revue chaque caractère spécial avec des exemples concrets. Que vous rédigiez une tâche cron pour un démon Linux, configuriez un planning GitHub Actions ou définissiez une règle AWS EventBridge, les mêmes concepts s'appliquent — avec quelques différences importantes entre plateformes expliquées au fil du texte.

Les cinq champs standard

Une expression cron standard comporte cinq champs séparés par des espaces, lus de gauche à droite : minutes, heures, jour du mois, mois et jour de la semaine. Chaque champ contraint le moment où la tâche s'exécute selon cette dimension. Une tâche ne s'exécute que lorsque les cinq champs correspondent simultanément.

# Champ          Position  Plage          Caractères spéciaux
# ─────────────────────────────────────────────────────────────
# Minute              1      0-59          * / , -
# Heure               2      0-23          * / , -
# Jour du mois        3      1-31          * / , - ? L W
# Mois                4      1-12 ou JAN-DEC   * / , -
# Jour de la semaine  5      0-7 (0=7=Dim) ou SUN-SAT  * / , - ? L #

Pour lire une expression comme 30 9 * * 1-5 : minute 30, heure 9, n'importe quel jour du mois, n'importe quel mois, jour de la semaine 1 à 5 (lundi à vendredi). Résultat : 9h30 chaque jour ouvré.

Champ 1 : Minutes (0–59)

Le champ des minutes indique à quelle(s) minute(s) de l'heure la tâche doit s'exécuter. 0 correspond au début de l'heure, 30 à la demi-heure, 59 à une minute avant le changement d'heure. L'utilisation de * exécute la tâche chaque minute.

Champ 2 : Heures (0–23)

Les heures utilisent le format 24 heures. 0 correspond à minuit, 12 à midi, 23 à 23h00. Il n'y a pas de notion AM/PM dans cron — une tâche à 9h00 du matin correspond à l'heure 9, et une tâche à 21h00 correspond à l'heure 21.

Champ 3 : Jour du mois (1–31)

Contrairement aux autres champs, le jour du mois commence à 1, pas à 0. Les valeurs valides vont de 1 à 31. Si vous spécifiez un jour qui n'existe pas dans un mois donné (par exemple, le jour 31 en avril), la tâche ne s'exécute tout simplement pas ce mois-là. Dans Quartz, le caractère spécial L représente le dernier jour du mois, quel que soit son nombre de jours.

Champ 4 : Mois (1–12)

Les valeurs de mois vont de 1 (janvier) à 12 (décembre). De nombreux planificateurs acceptent aussi des abréviations à trois lettres : JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC. Elles sont insensibles à la casse dans la plupart des implémentations.

Champ 5 : Jour de la semaine (0–7)

C'est le champ qui porte le plus de bagages historiques. 0 et 7 représentent tous deux le dimanche — c'est une particularité de compatibilité héritée de Unix. Lundi correspond à 1, mardi à 2, jusqu'au samedi à 6. Les noms à trois lettres fonctionnent également ici : SUN, MON, TUE, WED, THU, FRI, SAT.

Lorsque le jour du mois et le jour de la semaine sont tous deux spécifiés (aucun n'est *), la plupart des démons cron Unix appliquent une logique OU : la tâche s'exécute si l'un ou l'autre champ correspond. Cela surprend de nombreux développeurs. Si vous souhaitez « le 15, mais seulement si c'est un jour ouvré », vous devez gérer cette vérification supplémentaire dans le script de la tâche elle-même, pas dans l'expression cron.

Caractères spéciaux

Astérisque (*) — Toutes les valeurs

L'astérisque correspond à toutes les valeurs valides d'un champ. Dans le champ des minutes, * signifie les minutes 0 à 59. Dans le champ des mois, il désigne les 12 mois. C'est le caractère le plus courant dans les expressions cron.

Barre oblique (/) — Valeurs de pas

La barre oblique définit un intervalle de pas. */5 dans le champ des minutes signifie « toutes les 5 minutes ». Plus précisément, cela signifie « chaque valeur de la plage qui est divisible par 5 en commençant par la première valeur de la plage ». Ainsi, */5 en minutes donne 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55.

Les pas peuvent être combinés avec des plages : 10-30/5 dans le champ des minutes signifie toutes les 5 minutes entre la minute 10 et la minute 30, soit 10, 15, 20, 25, 30. Le pas commence à la borne inférieure de la plage.

Virgule (,) — Liste de valeurs

Les virgules créent une liste de valeurs spécifiques. 1,3,5 dans le champ des mois signifie janvier, mars et mai. 9,17 dans le champ des heures signifie 9h00 et 17h00. Vous pouvez lister autant de valeurs que nécessaire et les combiner avec d'autres constructions.

Tiret (-) — Plage

Un tiret spécifie une plage inclusive. 1-5 dans le champ du jour de la semaine signifie du lundi au vendredi. 9-17 dans le champ des heures signifie de 9h à 17h. Les plages sont inclusives aux deux extrémités.

Point d'interrogation (?) — Aucune valeur spécifique (Quartz uniquement)

Le cron Unix standard ne prend pas en charge ?. Dans Quartz Scheduler, il est utilisé dans les champs jour du mois ou jour de la semaine pour signifier « ce champ n'a pas d'importance ». Parce que Quartz ne peut pas toujours résoudre les conflits entre jour du mois et jour de la semaine, l'un des deux doit être défini à ? lorsque l'autre est spécifié. 0 0 15 * ? signifie « le 15 de chaque mois, quel que soit le jour de la semaine ». 0 0 ? * MON signifie « chaque lundi, quel que soit le jour du mois ».

L — Dernier (Quartz uniquement)

L dans le champ jour du mois signifie le dernier jour du mois. L dans le champ jour de la semaine signifie samedi, ou combiné avec un nombre (par ex. 5L), la dernière occurrence de ce jour de la semaine dans le mois. 5L correspond au dernier vendredi du mois.

W — Jour ouvré le plus proche (Quartz uniquement)

W dans le champ jour du mois trouve le jour ouvré (lundi–vendredi) le plus proche du jour spécifié. 15W signifie le jour ouvré le plus proche du 15. Si le 15 tombe un samedi, la tâche s'exécute le 14 (vendredi). Si c'est un dimanche, elle s'exécute le 16 (lundi). W ne traverse pas les frontières de mois.

Dièse (#) — Nième jour de la semaine du mois (Quartz uniquement)

# spécifie la Nième occurrence d'un jour de la semaine dans un mois. 5#2 signifie le deuxième vendredi du mois. 2#1 signifie le premier mardi. Si l'occurrence spécifiée n'existe pas dans un mois donné, la tâche ne s'exécute pas ce mois-là.

Schémas cron courants

# Chaque minute
* * * * *

# Chaque jour à minuit (00:00)
0 0 * * *

# Chaque jour à 9h30
30 9 * * *

# Chaque lundi à 8h00
0 8 * * 1

# Premier jour de chaque mois à midi
0 12 1 * *

# Toutes les 15 minutes
*/15 * * * *

# Jours ouvrés à 18h00
0 18 * * 1-5

Vous pouvez tester et valider n'importe laquelle de ces expressions avec l'outil Analyseur cron, qui affiche les cinq prochaines exécutions planifiées pour n'importe quelle expression et signale la syntaxe invalide en ligne. Utilisez le Convertisseur de timestamp si vous devez vérifier à quoi correspond un timestamp Unix spécifique dans votre fuseau horaire local.

L'extension à 6 champs : Quartz Scheduler

Quartz Scheduler — très répandu dans l'écosystème Java et adopté par de nombreux planificateurs d'entreprise — ajoute un champ de secondes obligatoire au début de l'expression. Le format devient : seconde minute heure jour-du-mois mois jour-de-la-semaine.

# Quartz 6 champs : seconde minute heure jour mois jour-semaine
# S'exécute exactement à 00 secondes, 30 minutes, chaque heure
0 30 * * * ?

# S'exécute à minuit chaque jour
0 0 0 * * ?

# S'exécute toutes les 5 secondes
0/5 * * * * ?

# Dernier jour du mois à 10h00
0 0 10 L * ?

# Dernier vendredi du mois à 15h00
0 0 15 ? * 6L

Principales différences avec le cron standard : le champ des secondes (0–59) est en premier et obligatoire ; le jour de la semaine utilise 1 (dimanche) à 7 (samedi), pas 0–6 ; ? est requis dans le champ jour du mois ou jour de la semaine lorsque l'autre est spécifié ; et L, W et # sont des caractères spéciaux valides.

Ne collez jamais une expression Quartz dans un crontab Unix sans supprimer le champ des secondes et ajuster la numérotation des jours de la semaine. Les analyseurs ne sont pas interchangeables.

Cron dans différents systèmes

Linux/Unix crontab (Vixie cron)

La forme originale et la plus répandue. Cinq champs séparés par des espaces, suivis de la commande. Les variables d'environnement comme CRON_TZ ou TZ définissent le fuseau horaire. Les crontabs utilisateur se modifient avec crontab -e ; les crontabs système résident dans /etc/cron.d/. Les raccourcis @reboot, @daily, @hourly, @weekly et @monthly sont largement pris en charge comme alias pour des schémas courants.

GitHub Actions

GitHub Actions utilise la syntaxe cron standard à 5 champs, mais le fuseau horaire est toujours UTC — il n'est pas possible de spécifier un fuseau horaire local dans l'expression elle-même. Les expressions sont évaluées au niveau du dépôt, pas par tâche. Notez que les workflows planifiés peuvent être retardés de plusieurs minutes lors des périodes de forte charge sur l'infrastructure de GitHub.

# Syntaxe de planification GitHub Actions (5 champs, UTC uniquement)
on:
  schedule:
    # S'exécute chaque jour à 02h30 UTC
    - cron: '30 2 * * *'
    # S'exécute chaque lundi à 09h00 UTC
    - cron: '0 9 * * 1'

La documentation officielle de GitHub Actions sur cron précise que l'intervalle minimum est de 5 minutes — les expressions qui s'exécuteraient plus fréquemment sont ignorées silencieusement.

AWS EventBridge (CloudWatch Events)

AWS EventBridge prend en charge à la fois les expressions de taux (rate(5 minutes)) et les expressions cron. Leur variante cron est à 6 champs mais diffère de Quartz : le jour de la semaine utilise les noms Sun–Sat ou 1–7 où 1 est dimanche, toutes les heures sont en UTC, et au moins l'un des champs jour du mois ou jour de la semaine doit être ?. AWS ne prend pas en charge les caractères W ou #.

# AWS EventBridge (cron en UTC, variante à 6 champs)
# S'exécute chaque jour à 10h00 UTC
cron(0 10 * * ? *)

# S'exécute à 18h00 le dernier jour ouvré de chaque mois
cron(0 18 L-1 * ? *)

Kubernetes CronJob

Kubernetes CronJob utilise la syntaxe cron standard à 5 champs. Le fuseau horaire est par défaut celui du processus kube-controller-manager (généralement UTC sur les clusters gérés). Kubernetes 1.25 a ajouté le champ timeZone à la spécification CronJob, permettant une configuration de fuseau horaire par tâche sans dépendre du fuseau horaire système.

Node.js (node-cron / cron npm)

Le package populaire node-cron prend en charge les expressions standard à 5 champs ainsi qu'un 6e champ de secondes optionnel en préfixe. Le package cron est compatible Quartz. Les deux prennent en charge les chaînes de fuseau horaire (par ex. America/New_York) comme option de constructeur. Consultez la documentation de votre package spécifique pour confirmer le format attendu.

Pièges courants

Hypothèses de fuseau horaire

Cron s'exécute dans le fuseau horaire du serveur ou du conteneur, qui est fréquemment UTC dans les environnements cloud. Une tâche censée s'exécuter à « 9h heure de bureau » définie comme 0 9 * * * s'exécutera à 9h00 UTC — ce qui peut correspondre à 4h, 5h ou 11h dans votre fuseau horaire local selon le décalage et l'heure d'été. Définissez toujours CRON_TZ, utilisez le champ de fuseau horaire de votre planificateur, ou convertissez explicitement votre heure cible en UTC. Le Convertisseur de fuseau horaire peut vous aider à trouver l'équivalent UTC pour n'importe quelle heure locale dans n'importe quel fuseau horaire.

Logique OU entre jour du mois et jour de la semaine

Dans le cron Unix, lorsque les champs jour du mois et jour de la semaine sont tous deux non-*, le démon exécute la tâche si l'un ou l'autre correspond. Ainsi, 0 9 15 * 1 s'exécute le 15 de chaque mois ET chaque lundi — pas seulement les lundis qui tombent le 15. Pour obtenir une logique ET, vous devez implémenter la vérification supplémentaire dans le script de la tâche lui-même.

Confusion entre valeurs de pas et plages

*/5 signifie « toutes les 5 minutes à partir de 0 » (0, 5, 10...). 5/5 signifie « toutes les 5 minutes à partir de 5 » (5, 10, 15...). 5-30/5 signifie « toutes les 5 minutes entre la minute 5 et la minute 30 » (5, 10, 15, 20, 25, 30). Mélanger ces éléments avec des plages peut produire des résultats inattendus si vous n'êtes pas précis quant à la valeur de départ.

Le piège « chaque seconde »

La résolution minimale de cron au format standard à 5 champs est d'une minute. Vous ne pouvez pas planifier une tâche cron pour qu'elle s'exécute chaque seconde ou toutes les quelques secondes via un crontab. Pour une planification sub-minute, utilisez une minuterie au niveau du langage (setInterval en Node.js, APScheduler en Python) ou un système de file d'attente dédié plutôt que cron. Si vous avez besoin d'une exécution toutes les 30 secondes, lancez deux tâches cron : une à * * * * * et une qui attend 30 secondes avant de s'exécuter.

Oublier la numérotation des mois

Dans le cron standard, les mois vont de 1 (janvier) à 12 (décembre). Dans certaines API de date des langages de programmation, les mois sont indexés à 0 (0 = janvier, 11 = décembre). Si vous générez des expressions cron par programmation à partir d'objets de date, vérifiez que vous n'avez pas un décalage de un dans le champ du mois.

Validez vos expressions

L'outil Analyseur cron de Toova affiche les cinq prochaines exécutions planifiées pour n'importe quelle expression, prend en charge la syntaxe à 5 champs et à 6 champs Quartz, et signale les valeurs invalides en ligne. Pour une vérification rapide, crontab.guru est un outil interactif bien connu qui décrit les expressions en langage naturel. Les deux méritent d'être mis en favoris.

Lorsque vous travaillez avec des timestamps et des heures planifiées, le Convertisseur de timestamp traduit entre les timestamps Unix et les dates lisibles par l'homme dans n'importe quel fuseau horaire. Pour les tâches impliquant une planification sensible au fuseau horaire, associez-le au Convertisseur de fuseau horaire pour vérifier les décalages, les transitions d'heure d'été et les équivalents UTC avant de rédiger votre expression finale.