Aide-mémoire Crontab : 50+ expressions cron, syntaxe et guide des planificateurs modernes
Une expression cron, ce sont cinq champs (minute, heure, jour du mois, mois, jour de la semaine) suivis d’une commande. Cette grammaire pilote l’ordonnancement Unix depuis 1979 et anime aujourd’hui les CronJobs Kubernetes, les GitHub Actions, AWS EventBridge et les déclencheurs cron de Vercel. Apprenez-la une fois, vous planifiez partout.
Cette page s’adresse aux développeurs qui ont besoin d’une expression tout de suite : une tâche Linux, un CronJob Kubernetes, un déclencheur GitHub Actions, ou bien comprendre pourquoi un job censé tourner toutes les cinq minutes ne se déclenche qu’à l’heure ronde. Descendez jusqu’au tableau de référence rapide pour des expressions prêtes à copier, sautez à la section Syntaxe décortiquée pour les règles de chaque champ, ou ouvrez le Générateur Crontab — une alternative à crontab guru, privacy-first, qui tourne dans votre navigateur — pour valider vos expressions en direct.
Tableau de référence rapide des expressions cron
Trente expressions qui couvrent environ 90 % des besoins réels de planification. Chacune est une expression cron POSIX à cinq champs valide. Collez-la dans crontab -e, dans un schedule: Kubernetes ou dans un cron: GitHub Actions.
| Planification | Expression cron | En français clair |
|---|---|---|
| Toutes les minutes | * * * * * | chaque minute, toute la journée, tous les jours |
| Toutes les 5 minutes | */5 * * * * | minutes 0, 5, 10, …, 55 |
| Toutes les 15 minutes | */15 * * * * | minutes 0, 15, 30, 45 |
| Toutes les 30 minutes | */30 * * * * | minutes 0 et 30 |
| Toutes les heures | 0 * * * * | au début de chaque heure |
| Toutes les 2 heures | 0 */2 * * * | heures 0, 2, 4, …, 22 |
| Toutes les 6 heures | 0 */6 * * * | heures 0, 6, 12, 18 |
| Deux fois par jour (9 h et 21 h) | 0 9,21 * * * | minute 0 des heures 9 et 21 |
| Chaque jour ouvré à 9 h | 0 9 * * 1-5 | lun.-ven. 09 h 00 |
| Chaque jour de week-end à 9 h | 0 9 * * 0,6 | sam. et dim. 09 h 00 |
| Tous les jours à minuit | 0 0 * * * | chaque jour à 00 h 00 |
| Tous les jours à 2 h 30 | 30 2 * * * | créneau batch en heure creuse |
| Chaque lundi à 9 h | 0 9 * * 1 | lundis 09 h 00 |
| Chaque vendredi à 17 h | 0 17 * * 5 | vendredis 17 h 00 |
| Chaque dimanche à minuit | 0 0 * * 0 | équivalent à @weekly |
| Le 1er du mois à minuit | 0 0 1 * * | jour 1 à 00 h 00, équivalent à @monthly |
| Le 15 de chaque mois à midi | 0 12 15 * * | créneau de paie en milieu de mois |
| Vérification du dernier jour (wrapper) | 0 0 28-31 * * + script | requiert une vérification de date |
| Trimestriel (1er jan./avr./juil./oct.) | 0 0 1 JAN,APR,JUL,OCT * | premier jour de chaque trimestre |
| Annuel (1er janvier) | 0 0 1 1 * ou @yearly | minuit du nouvel an |
| Toutes les 5 min, jours ouvrés 9 h-17 h | */5 9-17 * * 1-5 | polling en heures ouvrées |
| Toutes les 30 min le week-end | */30 * * * 0,6 | supervision sam./dim. |
| Deux fois par heure, 15 et 45 | 15,45 * * * * | décalé par rapport à la ruée du :00 |
| Premier lundi (wrapper) | 0 9 1-7 * 1 + vérif. ET | wrapper indispensable (voir plus bas) |
| Macros | @hourly @daily @weekly @monthly @yearly | non standard mais largement supportées |
| Au démarrage uniquement | @reboot | non standard, vixie cron uniquement |
Collez n’importe laquelle de ces expressions dans le Générateur Crontab pour obtenir un aperçu des cinq prochaines exécutions, la vérification la plus rapide avant déploiement.
Syntaxe cron décortiquée : les 5 champs
Une expression cron, ce sont cinq champs séparés par des espaces, plus une commande. Chaque champ contrôle une tranche de la planification. Cette grammaire revient à l’identique chez tous les planificateurs de ce guide.
┌──────────── minute (0 - 59)
│ ┌────────── hour (0 - 23)
│ │ ┌──────── day-of-month (1 - 31)
│ │ │ ┌────── month (1 - 12 or JAN-DEC)
│ │ │ │ ┌──── day-of-week (0 - 6 or SUN-SAT; 0 and 7 both mean Sunday)
│ │ │ │ │
* * * * * command-to-run
Moyen mnémotechnique : « Mon Hibou Dort Mieux Sam. » pour Minute, Heure, jour du Mois, Mois, jour de la Semaine. De gauche à droite, de la plus petite unité à la plus grande.
Valeurs autorisées champ par champ
| Champ | Plage | Alias | Notes |
|---|---|---|---|
| Minute | 0-59 | aucun | 0 signifie « pile à l’heure » |
| Heure | 0-23 | aucun | horloge 24 h ; 0 est minuit, 12 est midi |
| Jour du mois | 1-31 | aucun | les jours invalides pour un mois ne se déclenchent jamais en silence (31 février) |
| Mois | 1-12 | JAN, FEB, MAR, …, DEC | insensible à la casse |
| Jour de la semaine | 0-7 | SUN, MON, TUE, …, SAT | 0 et 7 désignent tous deux dimanche |
Les opérateurs en détail
Cinq opérateurs couvrent toutes les expressions cron standards :
| Opérateur | Signification | Exemple | Développe en |
|---|---|---|---|
* | n’importe quelle valeur | * * * * * | toutes les minutes |
, | liste | 0 9,12,17 * * * | 09 h 00, 12 h 00, 17 h 00 |
- | plage inclusive | 0 9-17 * * * | chaque heure de 09 h 00 à 17 h 00 |
/ | pas | */15 * * * * | minutes 0, 15, 30, 45 |
| combiné | composé | 0 9-12,14-17 * * * | matin + après-midi, déjeuner sauté |
L’opérateur de pas mérite qu’on s’y attarde. */N est ancré sur la plus petite valeur du champ, pas sur l’heure courante. */15 veut dire « minutes 0, 15, 30, 45 de chaque heure », pas « toutes les 15 minutes à partir de maintenant ». Vous sauvegardez à 12 h 03, la prochaine exécution est à 12 h 15. Avec une base non joker, 5/15 se lit « commencer à 5, puis tous les 15 » : minutes 5, 20, 35, 50.
Mois et jours de la semaine nommés
Écrivez les mois et les jours de la semaine sous forme de noms, sans tenir compte de la casse :
0 0 1 JAN,APR,JUL,OCT * # first of each quarter
0 9 * * MON-FRI # weekdays at 9 AM
0 17 * * FRI # Friday at 5 PM
Les noms sont plus lisibles en revue de code ; les formes numériques sont un peu plus portables. Choisissez un style par projet.
Macros non standards : @reboot, @daily et compagnie
La plupart des implémentations cron acceptent six raccourcis :
| Macro | Développe en | Signification |
|---|---|---|
@yearly / @annually | 0 0 1 1 * | une fois par an, 1er janvier à minuit |
@monthly | 0 0 1 * * | premier de chaque mois à minuit |
@weekly | 0 0 * * 0 | chaque dimanche à minuit |
@daily / @midnight | 0 0 * * * | chaque jour à minuit |
@hourly | 0 * * * * | au début de chaque heure |
@reboot | (spécial) | une fois au démarrage du démon cron |
Ces macros ne sont pas standards : vixie cron et cronie les acceptent, mais ni les CronJobs Kubernetes, ni GitHub Actions, ni AWS EventBridge. Pour des expressions portables, écrivez la forme à cinq champs. @reboot fonctionne rarement dans des conteneurs où le démon cron n’est pas le processus init.
50+ expressions cron à copier-coller (par cas d’usage)
Le tableau de référence rapide couvre les cas courants. Cette section descend dans six catégories avec des exemples plus denses.
Toutes les N minutes
* * * * * # every minute
*/2 * * * * # every 2 minutes
*/5 * * * * # every 5 minutes — the cron expression every 5 minutes case
*/10 * * * * # every 10 minutes
*/15 * * * * # every 15 minutes
*/30 * * * * # every 30 minutes
0,30 * * * * # explicit minutes 0 and 30 (same as */30)
*/45 * * * * # WARNING: fires at 0 and 45 only, then wraps
*/45 est un piège classique : la minute va de 0 à 59, donc l’expression se déclenche à 0 et 45 puis repart à zéro à l’heure suivante. Pour une vraie cadence de 45 minutes, il vous faut un worker externe.
Variantes horaires
0 * * * * # every hour at :00
30 * * * * # every hour at :30
0 */2 * * * # every 2 hours, even hour
0 */6 * * * # every 6 hours
0 */12 * * * # twice a day at 00:00 and 12:00
15 */2 * * * # every 2 hours, offset by 15 min (avoids :00 spike)
Quotidien à des horaires précis
0 0 * * * # midnight (= @daily / @midnight)
30 2 * * * # 02:30 — low-traffic batch window
0 9 * * * # 09:00
45 23 * * * # 23:45 — end-of-day rollups
0 9,12,17 * * * # three times daily
0 9-17 * * * # every hour from 09:00 through 17:00
Plannings hebdomadaires
0 9 * * 1-5 # weekdays at 9 AM
0 9 * * 0,6 # weekends at 9 AM
0 18 * * 5 # Fridays at 6 PM
0 0 * * 0 # Sunday at midnight (= @weekly)
0 9 * * MON,WED,FRI # Mon/Wed/Fri at 9 AM
*/30 9-17 * * 1-5 # every 30 min, business hours, weekdays
Mensuel et trimestriel
0 0 1 * * # 1st of month at midnight (= @monthly)
0 0 15 * * # 15th — payroll window
0 0 1,15 * * # 1st and 15th — semi-monthly
0 0 1 */3 * # quarterly: first of Jan, Apr, Jul, Oct
0 0 1 JAN,APR,JUL,OCT * # same, named months
0 0 28-31 * * # last few days — pair with a date-check wrapper
Le dernier jour du mois n’a pas d’expression POSIX native. Lancez un wrapper qui vérifie date -d tomorrow +%d = 01, ou utilisez un planificateur qui le gère nativement (Quartz a L, pas Kubernetes).
Annuel et raccourcis macro
0 0 1 1 * # Jan 1 at midnight (= @yearly / @annually)
0 0 25 12 * # Christmas at midnight
@yearly # = 0 0 1 1 *
@monthly # = 0 0 1 * *
@weekly # = 0 0 * * 0
@daily # = 0 0 * * *
@hourly # = 0 * * * *
@reboot # special: once on daemon start (vixie cron only)
Toutes ces expressions se collent dans le Générateur Crontab pour un aperçu des cinq prochaines exécutions, le smoke test le moins cher avant déploiement.
Cron vs timers systemd vs planificateurs cloud : matrice de décision
Cron est le choix par défaut, pas toujours le meilleur. Voici les sept planificateurs les plus courants comparés, utile pour trancher entre cron et timer systemd, entre CronJob Kubernetes et cron job Vercel, ou pour migrer de crontab vers du cloud managé.
| Fonctionnalité | vixie cron | timer systemd | CronJob K8s | schedule GHA | AWS EventBridge | Vercel Cron | Cloudflare Workers |
|---|---|---|---|---|---|---|---|
| Syntaxe des champs | POSIX 5 champs | spec OnCalendar | POSIX 5 champs + timeZone | POSIX 5 champs | Quartz 6 champs avec ? | POSIX 5 champs | POSIX 5 champs |
| Intervalle minimum | 1 minute | 1 seconde | 1 minute | best-effort, ≥15 min recommandé | 1 minute | 1 minute (plan Pro) | 1 minute |
| Fuseau explicite | CRON_TZ= | Persistent=true | spec.timeZone (1.27+) | UTC uniquement | ScheduleExpressionTimezone | UTC uniquement | UTC uniquement |
| Rattrapage d’exécutions manquées | non (utiliser anacron) | oui (Persistent=true) | oui (startingDeadlineSeconds) | non | oui | non | non |
| Retry / backoff | non | partiel | oui (backoffLimit) | retry à l’échec | oui | non | oui |
| Contrôle de concurrence | non (utiliser flock) | partiel | oui (concurrencyPolicy) | non | non | non | non |
Support @reboot | oui | oui (via OnBootSec=) | non | non | non | non | non |
Timers systemd : quand les préférer à cron
Sur du Linux à base de systemd, les timers sont une alternative sérieuse : syntaxe calendaire lisible, intégration au journal, rattrapage des exécutions manquées. Un timer et son service associé :
# daily-report.timer
[Unit]
Description=Run daily report at 9 AM
[Timer]
OnCalendar=*-*-* 09:00:00
Persistent=true
Unit=daily-report.service
[Install]
WantedBy=timers.target
# daily-report.service
[Unit]
Description=Daily report job
[Service]
Type=oneshot
ExecStart=/usr/local/bin/daily-report.sh
User=reporter
Activez avec systemctl enable --now daily-report.timer. La fonctionnalité clé est Persistent=true : si la machine était éteinte à 9 h, le timer se déclenche dès le démarrage, là où vixie cron n’a pas d’équivalent sans anacron. Pour le durcissement des services, voir nos bonnes pratiques de sécurité.
CronJob Kubernetes
Kubernetes enveloppe le planning POSIX de primitives pour la concurrence, l’historique et le fuseau explicite :
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-report
spec:
schedule: "0 2 * * *"
timeZone: "America/New_York" # Kubernetes 1.27+
concurrencyPolicy: Forbid # never run two at once
startingDeadlineSeconds: 300 # skip if delayed >5 min
jobTemplate:
spec:
backoffLimit: 2
template:
spec:
restartPolicy: OnFailure
containers:
- name: reporter
image: reporter:1.4.0
command: ["/usr/local/bin/report.sh"]
concurrencyPolicy: Forbid est votre équivalent de flock. Sans cela, un job qui dure trop longtemps s’empile sur son successeur. Voir la section de référence des champs pour tous les boutons disponibles.
Pièges du schedule GitHub Actions
GitHub Actions accepte le cron POSIX standard à cinq champs :
on:
schedule:
- cron: '0 9 * * 1-5' # weekdays at 9 AM UTC
Best-effort : sous forte charge sur les runners GitHub, les jobs peuvent partir avec plusieurs minutes de retard ou être sautés. Évitez les intervalles inférieurs à quinze minutes. Pas de réglage de fuseau, toujours UTC.
AWS EventBridge : six champs façon Quartz
AWS EventBridge utilise un cron à saveur Quartz avec six champs et un ? obligatoire dans l’un des deux champs de jour :
cron(0 9 * * ? *)
Ordre des champs : Minutes Hours Day-of-month Month Day-of-week Year. L’un des deux champs de jour doit valoir ? quand l’autre est restreint (la manière Quartz de lever l’ambiguïté OR de POSIX). Une copie directe depuis un crontab Linux échoue à la validation.
Vercel Cron, Cloudflare Workers, Render Cron Jobs
Les plateformes serverless plus récentes se standardisent sur du POSIX à cinq champs. Un cron job Vercel vit dans vercel.json sous la forme { "crons": [{ "path": "/api/cron/nightly", "schedule": "0 2 * * *" }] }. Les Cron Triggers de Cloudflare Workers passent par wrangler.toml :
[triggers]
crons = ["*/15 * * * *", "0 9 * * 1-5"]
Render utilise render.yaml. Les trois tournent en UTC, sans override de fuseau par planning. Pensez UTC dès la conception.
7 pièges du débogage cron (et comment les attraper)
La plupart des rapports « mon cron job ne tourne pas » remontent à l’une de ces sept causes racines. Parcourez la liste avant d’incriminer le planificateur.
Piège 1 : PATH minimal
Cron démarre les jobs avec un $PATH minimal, généralement /usr/bin:/bin. Votre shell interactif a /usr/local/bin, ~/.cargo/bin et une douzaine d’entrées de .bashrc. Aucune n’existe sous cron. C’est le problème numéro un de variable d’environnement dans le débogage cron.
Symptôme : node: command not found. Correctif : définissez PATH en tête de crontab, ou utilisez des chemins absolus.
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin
*/15 * * * * /usr/local/bin/poll-api.sh
0 9 * * * /home/deploy/.cargo/bin/my-rust-cli
Piège 2 : stdout et stderr perdus en silence
Par défaut, la sortie de cron part dans un spool mail que personne ne lit. Le job échoue en silence. Redirigez les deux flux :
*/15 * * * * /usr/local/bin/job.sh >> /var/log/job.log 2>&1
Pour du JSON en sortie, passez par jq ; pour extraire des lignes de log, voyez notre aide-mémoire regex. Avec les timers systemd, journalctl -u your-timer.service capture la sortie.
Piège 3 : décalage de fuseau entre dev et prod
Vous avez écrit 0 9 * * * sur votre portable à New York, en visant 9 h heure de l’Est. Le serveur tourne en UTC. Le cron se déclenche à 9 h UTC, soit 4 h heure de l’Est, avant que personne ne le remarque. Correctif : passez les serveurs en UTC et écrivez vos plannings en UTC, ou épinglez le fuseau explicitement.
CRON_TZ=America/New_York
0 9 * * * /usr/local/bin/morning-report.sh
CRON_TZ fonctionne avec vixie cron 3.0+ ; Kubernetes 1.27+ a spec.timeZone ; AWS EventBridge a ScheduleExpressionTimezone ; GitHub Actions reste toujours en UTC. Pour UTC, heure d’été et arithmétique epoch, voir notre guide du timestamp Unix.
Piège 4 : % non échappé dans les commandes
Cron traite les % non échappés comme des sauts de ligne : le reste de la ligne est envoyé à la commande comme entrée standard. Donc date +"%Y-%m-%d" casse. Échappez chaque % en \%, ou sortez la logique dans un script :
0 0 * * * echo "Run at $(date +"\%Y-\%m-\%d")" >> /tmp/log
Piège 5 : exécutions qui se chevauchent
Un job en */5 * * * * qui prend parfois sept minutes va lancer l’occurrence suivante avant que la précédente ne soit finie. Deux copies se battent sur la même ligne, le même fichier de verrou et le même quota d’API. Sérialisez avec flock :
*/5 * * * * flock -n /tmp/job.lock /usr/local/bin/job.sh
-n quitte tout de suite si le verrou est tenu. Sous Kubernetes, mettez concurrencyPolicy: Forbid. Les permissions du fichier de verrou comptent ; voir les bonnes pratiques de sécurité.
Piège 6 : @reboot dans les conteneurs
@reboot se lance une seule fois au démarrage du démon cron. Dans une VM, cela correspond au boot. Dans un conteneur, le démon cron n’est généralement pas PID 1 et peut même ne pas tourner du tout. N’utilisez pas @reboot dans des conteneurs ; mettez la logique « une fois au démarrage » dans votre entrypoint ou dans un init container.
Piège 7 : sémantique OR POSIX entre jour du mois et jour de la semaine
Le piège cron le plus coûteux. Règle POSIX : quand le jour du mois et le jour de la semaine sont tous deux restreints (aucun n’est *), le planning se déclenche dès que l’un ou l’autre correspond.
0 0 1 * 5 ressemble à « minuit le 1er, uniquement les vendredis », mais se déclenche le 1er ET chaque vendredi, soit six à dix déclenchements supplémentaires par mois.
# WRONG: looks like "1st of the month, only if Friday"
0 0 1 * 5
# RIGHT: pick one constraint
0 0 1 * * # every 1st of the month
0 0 * * 5 # every Friday
# AND semantics need a wrapper
0 0 1-7 * 5 [ "$(date +\%u)" = "5" ] && /script # first Friday only
Collez les expressions suspectes dans le Générateur Crontab : l’aperçu de la prochaine exécution rend le piège OR évident.
Planificateurs modernes : quand NE PAS utiliser cron
Cron convient pour « exécuter cette commande à peu près à cette heure, à cadence fixe ». Il convient mal à plusieurs problèmes voisins :
- Workflows avec dépendances (exécuter A, puis B si A a réussi) → Airflow, Prefect, Dagster.
- Retry, backoff exponentiel, dead-letter queues → Temporal, AWS Step Functions, Sidekiq.
- Intervalles inférieurs à la minute → un worker long-lived qui dort entre deux itérations.
- Précision à la seconde → un démon dédié ; les planificateurs managés se déchargent de la précision.
- Travail piloté par événement → webhooks, files de messages, flux change-data-capture.
Cron ne disparaît pas pour autant : Airflow, Step Functions et Sidekiq acceptent tous des expressions cron pour l’entrée de leurs workflows. La grammaire à cinq champs reste réutilisable.
Référence des champs CronJob Kubernetes
La matrice de décision plus haut montrait un CronJob minimal. La référence complète des champs pour la syntaxe CronJob Kubernetes :
| Champ | Défaut | Ce qu’il fait |
|---|---|---|
schedule | requis | expression cron POSIX 5 champs |
timeZone | TZ du controller | fuseau explicite (1.27+) ; utiliser des noms IANA |
concurrencyPolicy | Allow | Forbid saute les nouvelles exécutions tant que la précédente tourne ; Replace l’annule |
startingDeadlineSeconds | sans limite | saute si le retard dépasse cette valeur |
successfulJobsHistoryLimit | 3 | nombre de Jobs réussis à conserver |
failedJobsHistoryLimit | 1 | nombre de Jobs échoués à conserver |
suspend | false | pause sans suppression |
backoffLimit | 6 | retries du Pod avant que le Job soit marqué Failed |
activeDeadlineSeconds | non défini | plafond dur sur la durée du Pod |
ttlSecondsAfterFinished | non défini | suppression automatique du Job après ce délai en secondes |
Deux pièges courants : oublier timeZone fait suivre au planning le fuseau de l’hôte du kube-controller-manager (imprévisible sur du Kubernetes managé) ; sur un planning à la minute, la valeur par défaut successfulJobsHistoryLimit: 3 accumule trois objets Job par minute si ttlSecondsAfterFinished n’est pas défini.
Équivalents cron multi-plateformes
launchd sous macOS. Apple recommande launchd plutôt que cron. Un job launchd est un .plist dans ~/Library/LaunchAgents/ :
<plist version="1.0"><dict>
<key>Label</key><string>com.example.daily</string>
<key>ProgramArguments</key><array><string>/usr/local/bin/daily.sh</string></array>
<key>StartCalendarInterval</key>
<dict><key>Hour</key><integer>9</integer><key>Minute</key><integer>0</integer></dict>
</dict></plist>
Chargez avec launchctl load ~/Library/LaunchAgents/com.example.daily.plist. Contrairement à cron, launchd rattrape les exécutions manquées après un sleep/wake.
Planificateur de tâches Windows via schtasks :
schtasks /create /tn "DailyReport" /tr "C:\scripts\report.bat" /sc DAILY /st 09:00
schtasks /create /tn "EveryFifteen" /tr "C:\scripts\poll.bat" /sc MINUTE /mo 15
Sous WSL, le cron Linux natif fonctionne mais s’arrête à la fin de la session ; utilisez le planificateur de tâches pour lancer des jobs WSL en continu.
Cron dans les conteneurs Docker. La plupart des images slim (alpine, debian-slim, distroless) sont livrées sans démon cron. Installez cronie ou busybox-cron et lancez-le en PID 1 avec tini ou s6-overlay. Dans la plupart des cas, un CronJob Kubernetes reste préférable.
Astuces et patterns avancés
Dernier jour du mois
Cron n’a pas d’opérateur natif « dernier jour ». Tournez chaque jour dans la fenêtre 28-31 et regardez si demain est le 1er :
0 23 28-31 * * [ "$(date -d tomorrow +\%d)" = "01" ] && /usr/local/bin/eom.sh
Nième jour de la semaine du mois
« Premier lundi » utilise le même pattern de wrapper : restreignez aux jours 1-7, puis vérifiez le jour de la semaine :
0 9 1-7 * * [ "$(date +\%u)" = "1" ] && /usr/local/bin/first-monday.sh
Pour « dernier vendredi », prenez les jours 25-31 et ajoutez la vérification de jour de la semaine.
Décalage aléatoire pour étaler la charge
Quand de nombreuses machines exécutent le même cron, 0 0 * * * produit un thundering herd à minuit UTC. Saupoudrez d’un délai aléatoire :
RANDOM_DELAY=10 # cronie / anacron, in minutes
0 0 * * * /usr/local/bin/job.sh
0 0 * * * sleep $((RANDOM \% 600)); /usr/local/bin/job.sh # portable
Supervision par heartbeat
Cron échoue en silence. Le pattern dead-man’s-switch : le job ping un service de supervision après chaque exécution réussie ; le service alerte quand un ping attendu n’arrive pas. Healthchecks.io, Cronitor et Dead Man’s Snitch proposent des paliers gratuits.
*/15 * * * * /usr/local/bin/job.sh && curl -fsS --retry 3 https://hc-ping.com/your-uuid
Pour une logique de supervision qui se branche selon les codes de réponse (200 sain, 429 rate-limited, 503 dégradé), voir notre aide-mémoire des codes HTTP.
L’idempotence est une propriété du job, pas du planificateur
Cron n’a ni retry, ni rattrapage des exécutions manquées, ni contrôle de concurrence. Le correctif le plus fiable consiste à rendre le job lui-même rejouable sans risque. Au lieu de « envoyer le rapport du jour à 9 h », concevez-le comme « envoyer le rapport du jour s’il n’a pas déjà été envoyé ». Exécutions manquées, doublons et rattrapages manuels convergent alors vers le même état.
FAQ
*/5 * * * * veut-il vraiment dire toutes les 5 minutes ?
Presque : */5 * * * * est ancré sur la minute 0, pas sur « toutes les 5 minutes à partir de maintenant ». L’expression se déclenche aux minutes 0, 5, 10, …, 55 de chaque heure. Le pas */N est relatif à la plus petite valeur du champ, pas à l’heure courante. Vous sauvegardez à 12 h 03, la prochaine exécution est à 12 h 05, pas 12 h 08.
Que signifie 0 0 * * * en cron ?
0 0 * * * veut dire tous les jours à minuit (00 h 00) dans le fuseau local du serveur. Champs : minute 0, heure 0, n’importe quel jour du mois, n’importe quel mois, n’importe quel jour de la semaine. Équivalent aux macros @daily ou @midnight. Pour épingler le fuseau, ajoutez CRON_TZ=America/New_York en tête de crontab.
Comment exécuter un cron job toutes les 30 secondes ?
Impossible avec du cron POSIX standard : la granularité minimale est d’une minute. Trois contournements : deux jobs décalés en * * * * * avec un sleep 30 && sur l’un ; un timer systemd avec OnCalendar=*:*:0/30 ; ou un worker long-lived qui dort entre deux itérations. Le dernier est généralement le bon choix.
Quel fuseau cron utilise-t-il par défaut ?
Le fuseau système local du serveur (/etc/timezone ou la variable d’environnement TZ). Un cron à 9 h sur un serveur en UTC se déclenche à 4 h heure de l’Est. Correctif : posez CRON_TZ= en tête de crontab, ou mettez les serveurs en UTC et concevez les plannings en UTC. GitHub Actions reste toujours en UTC ; Kubernetes 1.27+ supporte spec.timeZone.
Pourquoi mon cron job ne tourne-t-il pas ?
Si votre tâche cron ne s’exécute pas, vérifiez dans l’ordre : le démon cron tourne-t-il (systemctl status cron) ; $PATH est-il défini dans la crontab ; stderr est-il capturé (>> log 2>&1) ; la crontab de l’utilisateur est-elle chargée (crontab -l) ; les % sont-ils échappés dans les commandes ; le fuseau est-il bien celui attendu. La plupart des « ne tourne pas » sont le deuxième ou le troisième point.
La syntaxe CronJob Kubernetes est-elle la même que celle du cron Linux ?
Oui pour le champ schedule : les deux utilisent du cron POSIX à cinq champs. Kubernetes ajoute spec.timeZone (1.27+), concurrencyPolicy pour le contrôle des chevauchements, startingDeadlineSeconds pour le rattrapage et suspend: true pour mettre en pause. Le cron Linux n’a rien de tout cela ; passez par flock et anacron.
Quelle est la différence entre @reboot et @daily ?
@daily est une macro pour 0 0 * * *, soit tous les jours à minuit sur un planning fixe. @reboot s’exécute une fois au démarrage du démon cron, sans planning récurrent. @reboot est supporté par vixie cron et cronie, mais pas par les CronJobs Kubernetes, GitHub Actions ou AWS EventBridge. Dans des conteneurs, @reboot se déclenche rarement.
Quelle est la différence entre cron et crontab ?
cron est le démon en arrière-plan qui exécute les tâches planifiées ; crontab est le fichier qui les liste (et la commande crontab qui sert à le modifier). Le démon lit chaque crontab utilisateur selon un planning et exécute les commandes dont l’heure d’exécution correspond à l’expression cron. Bref, cron est le moteur, crontab est la recette.