Cron — Syntaxe crontab
Syntaxe, champs, exemples courants et pièges à éviter avec les tâches planifiées Linux.
Syntaxe de base
* * * * * commande
┬ ┬ ┬ ┬ ┬
│ │ │ │ │
│ │ │ │ └── Jour de la semaine (0=dim, 7=dim aussi)
│ │ │ └──── Mois (1-12)
│ │ └────── Jour du mois (1-31)
│ └──────── Heure (0-23)
└────────── Minute (0-59)Piège courant : le champ « jour de la semaine » utilise 0 et 7 pour dimanche (contrairement à la plupart des API qui commencent à 1).
Champs avancés
| Syntaxe | Exemple | Sens |
|---|---|---|
| Valeur unique | 5 | À 5h |
| Plage | 1-5 | De 1 à 5 |
| Liste | 1,3,5 | Les valeurs 1, 3 et 5 |
| Pas | */15 | Toutes les 15 unités (0, 15, 30, 45) |
| Générique | * | Toutes les valeurs |
Combiner les opérateurs :
# Lun et mer, tous les 2h, entre 8h et 18h
0 8-18/2 * * 1,3
# Le 1er de chaque mois à minuit
0 0 1 * *
# Toutes les 10 min en semaine, toutes les 30 min le week-end
*/10 8-18 * * 1-5
*/30 0-7,19-23 * * 0,6Fichiers spéciaux (au lieu de champs)
| Fichier | Équivalent | Usage |
|---|---|---|
@reboot | — | Une seule fois au démarrage |
@yearly | 0 0 1 1 * | Annuel, 1er janv. à minuit |
@monthly | 0 0 1 * * | Mensuel, 1er du mois |
@weekly | 0 0 * * 0 | Hebdo, dim. à minuit |
@daily | 0 0 * * * | Quotidien, minuit |
@hourly | 0 * * * * | Toutes les heures |
Édition et vérification
# Éditer la crontab de l'utilisateur courant
crontab -e
# Voir la crontab actuelle
crontab -l
# Installer un fichier comme crontab
crontab /chemin/vers/fichier.cron
# Supprimer la crontab
crontab -r
# Éditer la crontab d'un autre utilisateur (root)
crontab -u alice -eBonnes pratiques
- Variables d’environnement : définir dans la crontab ou dans le script. Les environnements systemd/user ne sont pas les mêmes qu’un shell interactif.
# Dans la crontab
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=admin@example.com- Output : rediriger la sortie vers un fichier ou
/dev/nullpour éviter les emails de spam.
# Envoyer uniquement les erreurs par email
* * * * * /opt/scripts/monitor.sh >> /dev/null 2>&1
# Sauvegarder stdout + stderr dans un fichier
* * * * * /opt/scripts/job.sh >> /var/log/job.log 2>&1- Chemins absolus : toujours utiliser des chemins absolus dans les commandes.
# ✅
0 2 * * * /usr/bin/mysqldump -u root mydb > /backup/db.sql
# ❌ Risqué : le PATH de crontab est minimal
0 2 * * * mysqldump -u root mydb > /backup/db.sql- Globs dans les chemins : les globes (
*,?) ne sont pas interprétés dans les crontabs. Utiliserfindoubash -cpour les expansions.
# ❌ Ne fonctionne pas (le * n'est pas expandé)
0 0 * * * rm /backup/*.sql
# ✅ Utiliser bash -c
0 0 * * * bash -c 'rm /backup/*.sql'Pièges courants
| Piège | Symptôme | Solution |
|---|---|---|
| Pas de PATH configuré | Commande « not found » | Ajouter PATH=... dans la crontab |
| Script non exécutable | Erreur silencieuse | chmod +x script.sh |
| Horloge système incorrecte | Tâches exécutées à un mauvais moment | Vérifier avec date et synchroniser NTP (timedatectl status) |
| Journal vide | Impossible de déboguer | Rediriger vers un fichier de log ou consulter journalctl -u cron |
| Tâche ne se lance pas après reboot | Obligé de relancer cron manuellement | Utiliser @reboot ou configurer systemd timer |
| Interpréteur non spécifié | Script Python/Node qui ne tourne pas | Lier l’interpréteur explicitement : */5 * * * * /usr/bin/python3 /opt/script.py |
Cron vs systemd timers
Pour les nouvelles tâches critiques, préférer un systemd timer à un cron classique :
# Créer /etc/systemd/system/mon-job.timer
[Unit]
Description=Exécution périodique du job
[Timer]
OnCalendar=*-*-* *:00:00
Persistent=true
[Install]
WantedBy=timers.target
# Créer /etc/systemd/system/mon-job.service
[Unit]
Description=Mon job périodique
[Service]
Type=oneshot
ExecStart=/opt/scripts/mon-job.shsystemctl enable --now mon-job.timer
systemctl list-timersAvantage : journalctl capture les logs, pas de problème de PATH, la tâche est reprise automatiquement si elle a manqué son créneau (
Persistent=true).
Quick Reference
| Besoin | Syntaxe |
|---|---|
| Toutes les 5 minutes | */5 * * * * |
| Toutes les heures au jour le jour | 0 * * * * |
| Chaque jour à 3h du matin | 0 3 * * * |
| Premier jour de chaque mois | 0 0 1 * * |
| Lundi de chaque semaine | 0 0 * * 1 |
| Au démarrage de la machine | @reboot /opt/scripts/start.sh |
| Toutes les 15 minutes en journée | */15 8-20 * * * |
Consulté chaque fois qu’on oublie l’ordre des champs — parce que month day week reste le plus contre-intuitif.