⚙️ Crontab (Linux) – Planification de Tâches
Guide complet IDEO-Lab sur le daemon cron, la syntaxe crontab et la gestion des tâches.
Concept : cron (Daemon)
Le service (daemon crond) qui s'exécute en fond.
Concept : crontab (Fichier)
Le fichier de configuration ("table") qui liste les tâches.
crontab Configurationvs. systemd.timer
L'alternative moderne (plus complexe, plus puissante).
systemd TimersSyntaxe : Les 5 Champs (Temps)
m h dom mon dow (Minute, Heure, JourM, Mois, JourS).
Syntaxe : * (Astérisque)
Caractère "Joker" (wildcard). Signifie "chaque".
* WildcardSyntaxe : , (Listes) & - (Intervalles)
0,15,30 (Liste) et 9-17 (Intervalle).
Syntaxe : */n (Pas)
"Step values". (*/15 = "Toutes les 15 minutes").
Syntaxe : La Commande
La 6ème partie. (Chemins absolus recommandés).
Commande PATHSyntaxe : Chaînes Spéciales
@reboot, @daily, @hourly, @monthly.
CLI : crontab -e
Editer le crontab de l'utilisateur (via $EDITOR).
CLI : crontab -l
Lister le crontab de l'utilisateur (Lecture seule).
crontab -l ListerCLI : crontab -r (Danger)
Remove (Supprimer) le crontab. (Sans confirmation !)
crontab -r Supprimer DangerPiège : $PATH (Environnement)
Le $PATH de cron est minimal. (Utiliser chemins absolus).
Gestion des Logs (stdout/stderr)
Redirection (> log 2>&1) vs Silence (> /dev/null).
Gestion des Logs (MAILTO)
Variable MAILTO="" (Désactiver les emails).
Niveau 1 : Crontab Utilisateur
crontab -e (Stocké dans /var/spool/cron/).
Niveau 2 : Crontab Système
Le fichier /etc/crontab (Champ "Utilisateur" requis).
Niveau 3 : /etc/cron.d/
Le dossier "Drop-in" (pour les paquets/apps).
/etc/cron.d Drop-inNiveau 4 : cron.daily/hourly...
Dossiers de scripts (gérés par anacron ou run-parts).
Outil : anacron
Exécute les tâches "manquées" (ex: PC portable éteint).
anacron DesktopCheat-sheet : Syntaxe
Exemples (Toutes les 5 min, 3h du matin Lundi...).
Cheatsheet Exemplescron (Le Daemon)cron est un gestionnaire de tâches (Job Scheduler) standard sur les systèmes Unix/Linux. C'est l'un des outils d'automatisation les plus anciens et les plus fiables.
Le nom "cron" vient du grec "chronos" (χρόνος), qui signifie "temps".
Le Daemon crond
Le "vrai" cron est un daemon (un service/processus d'arrière-plan) appelé crond.
Son travail est très simple :
- Démarrer au boot du système (géré par
systemdouinit). - Se "réveiller" (Tick) toutes les 60 secondes (à :00).
- Lire ses fichiers de configuration (les "Crontabs", voir 1.2).
- Vérifier si l'heure/date actuelle correspond à une règle.
- Si oui, exécuter la commande associée.
- Se "rendormir" (Sleep) pendant 59 secondes.
crontab (La "Table")crontab (abréviation de "cron table") est le fichier texte qui contient la liste des tâches (jobs) à exécuter.
Il ne faut pas éditer ce fichier directement. On utilise toujours la commande crontab -e (voir 4.1) pour l'éditer.
Niveaux de Crontab
Il existe deux "types" de crontabs (qui co-existent) :
- 1. Crontab Utilisateur (User Crontab) :
- Chaque utilisateur (
root,www-data,bob) peut avoir son propre crontab. - Géré via
crontab -e. - Fichiers stockés dans
/var/spool/cron/crontabs/. - S'exécute avec les permissions de cet utilisateur.
- Chaque utilisateur (
- 2. Crontab Système (System Crontab) :
- Un fichier "global" (
/etc/crontab). - Des fichiers "drop-in" (
/etc/cron.d/). - (Voir 6.2 et 6.3).
- Un fichier "global" (
cron vs. systemd.timerSur les distributions Linux modernes (RHEL 7+, Debian 8+, Ubuntu 16.04+), systemd (le gestionnaire de services PID 1) offre sa propre alternative à cron : les systemd.timer.
cron (Le Classique)
- Avantages :
- Simple : La syntaxe "5 étoiles" est universelle et facile à lire pour les tâches simples.
- Portable : Fonctionne sur tous les systèmes Unix/Linux (même non-systemd, *BSD, macOS).
- Niveau Utilisateur :
crontab -eest très facile pour un utilisateur (non-root).
- Inconvénients :
- Logging faible : (Voir 5.2) Les logs (
stdout) sont envoyés par email (MAILTO), ce qui est souvent indésirable. - Environnement (PATH) : (Voir 5.1) Gère mal l'environnement (
$PATHminimaliste). - Manque de fonctionnalités : Pas de gestion de dépendances, de Cgroups, ou de "jitter" (délai aléatoire) facile.
- Logging faible : (Voir 5.2) Les logs (
systemd.timer (Le Moderne)
Fonctionne avec 2 fichiers : un .timer (le "Quand") et un .service (le "Quoi").
# /etc/systemd/system/backup.timer [Unit] Description=Lancer le backup tous les jours à 2h [Timer] OnCalendar=daily # (ou 'OnCalendar=02:00:00') AccuracySec=1m Persistent=true [Install] WantedBy=timers.target
# /etc/systemd/system/backup.service [Unit] Description=Script de Backup [Service] ExecStart=/usr/local/bin/backup.sh
- Avantages :
- Intégration (Logs) :
stdout/stderrvont directement dansjournald(journalctl -u backup.service). - Puissant : Gère les dépendances (
After=), la QoS (CPUShares=), le "Jitter" (RandomizedDelaySec=). - Granularité : Peut s'exécuter à la seconde (pas
cron).
- Intégration (Logs) :
- Inconvénient :
- Verbeux (2 fichiers), complexe pour les tâches simples, non portable (Linux/systemd uniquement).
Une ligne crontab (utilisateur) est composée de 6 champs (5 pour le temps, 1 pour la commande).
.---------------- Minute (m) | .------------- Heure (h) | | .---------- Jour du Mois (dom - Day of Month) | | | .------- Mois (mon - Month) | | | | .---- Jour de la Semaine (dow - Day of Week) | | | | | * * * * * /chemin/vers/la/commande
| Champ | Nom | Plage de Valeurs |
|---|---|---|
m | Minute | 0-59 |
h | Heure | 0-23 (Format 24h) |
dom | Jour du Mois (Day of Month) | 1-31 |
mon | Mois | 1-12 (ou Jan, Feb, Mar...) |
dow | Jour de la Semaine (Day of Week) | 0-7 (0 et 7 sont Dimanche. 1=Lundi, 6=Samedi) (ou Sun, Mon...) |
* (Astérisque / Wildcard)L'astérisque * est un "wildcard" (joker) qui signifie "chaque" ou "tous".
Exemples (*)
# (m h dom mon dow) # 1. Toutes les minutes de chaque jour # (Le "Tick" de cron) * * * * * /path/to/script.sh # 2. À 2h00 du matin, tous les jours # (Minute=0, Heure=2, Reste=*) 0 2 * * * /path/to/backup.sh # 3. Tous les Dimanches, à 4h05 du matin # (Minute=5, Heure=4, JourS=0) 5 4 * * 0 /path/to/weekly_report.sh # (Note: 0 ou 7 = Dimanche)
, (Listes) & - (Intervalles), (Virgule) - Listes
La virgule permet de spécifier une liste de valeurs.
# (m h dom mon dow) # Exécuter à 0, 15, 30, et 45 minutes # (Toutes les heures) 0,15,30,45 * * * * /path/to/script.sh # Exécuter à 8h00 et 17h00 (H=8, H=17) 0 8,17 * * * /path/to/script.sh
- (Tiret) - Intervalles (Ranges)
Le tiret permet de spécifier un intervalle (bornes incluses).
# (m h dom mon dow) # Exécuter toutes les minutes, # pendant les heures de bureau (de 9h à 17h) * 9-17 * * * /path/to/script.sh # Exécuter à 5h du matin, # les jours de semaine (Lundi à Vendredi) 5 5 * * 1-5 /path/to/script.sh
*/n (Pas / Step)L'opérateur */n (step value) permet de définir une récurrence (ex: "toutes les N minutes").
Exemples (*/n)
# (m h dom mon dow) # 1. Toutes les 15 minutes # (équivaut à 0,15,30,45) */15 * * * * /path/to/script.sh # 2. Toutes les 2 heures # (à 0h, 2h, 4h, 6h...) 0 */2 * * * /path/to/script.sh # 3. Tous les 10 jours (1er, 11e, 21e) 0 0 */10 * * /path/to/script.sh
Combiner (Intervalle + Pas)
# Toutes les 5 minutes, # uniquement pendant les heures de bureau (9h-17h) */5 9-17 * * 1-5 /path/to/script.sh
Le 6ème champ (et tout ce qui suit) est la commande shell (sh) à exécuter.
Chemins Absolus (Bonne Pratique)
Le cron s'exécute avec un $PATH minimal (voir 5.1). Ne jamais supposer que php ou python est dans le path.
# MAUVAIS (Risqué) * * * * * php mon_script.php # BON (Robuste) * * * * * /usr/bin/php /home/user/web/mon_script.php # BON (Script Shell) * * * * * /home/user/scripts/mon_script.sh
Caractère % (Le Piège)
Attention : Le caractère % a une signification spéciale dans cron (c'est un "saut de ligne", tout ce qui suit est passé au stdin).
Si vous utilisez des commandes (comme date) qui utilisent %, vous devez l'échapper (\).
# MAUVAIS (Cassé) * * * * * echo "Date: $(date +%Y-%m-%d)" # BON (Échappé) * * * * * echo "Date: $(date +\%Y-\%m-\%d)"
@reboot)Pour les intervalles de temps courants, cron (Vixie) fournit des "chaînes spéciales" (raccourcis) lisibles.
| Chaîne Spéciale | Équivalent (m h dom mon dow) | Description |
|---|---|---|
@reboot | (Aucun) | Exécuter 1 fois, au démarrage du daemon crond (au boot). |
@hourly | 0 * * * * | Toutes les heures, à la minute 0. |
@daily | 0 0 * * * | Tous les jours, à 00h00 (minuit). |
@weekly | 0 0 * * 0 | Toutes les semaines, Dimanche à 00h00. |
@monthly | 0 0 1 * * | Tous les mois, le 1er à 00h00. |
@yearly | 0 0 1 1 * | Tous les ans, le 1er Janvier à 00h00. |
Exemple (@reboot)
Très utile pour lancer des services (non-critiques) au démarrage, sans systemd.
# Lancer mon script 'start_server.sh' au redémarrage @reboot /home/user/start_server.sh
crontab -e (Edit)crontab -e (Edit) est la seule commande que vous devriez utiliser pour modifier votre crontab (utilisateur).
Fonctionnement
crontab -eouvre un éditeur de texte temporaire (défini par la variable$EDITOR, ex:nano,vim) avec le contenu actuel de votre crontab.- Vous modifiez le fichier temporaire.
- Vous sauvegardez et quittez l'éditeur.
crontabvalide la syntaxe du fichier temporaire.- Si la syntaxe est valide, il installe le fichier dans
/var/spool/cron/(le "vrai" emplacement). - Si la syntaxe est invalide (ex: "
*/100 * * * *"), il refuse l'installation et vous propose de re-modifier.
# Éditer le crontab de l'utilisateur actuel $ crontab -e # Éditer le crontab d'un *autre* utilisateur (en tant que root) $ sudo crontab -e -u www-data
crontab -l (List)crontab -l (List) est la commande (lecture seule) pour afficher le contenu du crontab installé.
Usage (Diagnostic & Backup)
# Afficher le crontab de l'utilisateur actuel $ crontab -l # (Affiche le contenu) # */5 * * * * /home/user/script.sh # Afficher le crontab de 'www-data' (en tant que root) $ sudo crontab -l -u www-data # BONNE PRATIQUE : Sauvegarder avant d'éditer ! $ crontab -l > crontab_backup_$(date +%F).txt $ crontab -e
crontab -r (Danger)crontab -r (Remove) supprime (efface) l'intégralité du fichier crontab de l'utilisateur.
DANGER : crontab -r ne demande AUCUNE CONFIRMATION.
Les touches e et r sont voisines sur un clavier QWERTY. Il est très (très) fréquent pour les administrateurs (fatigués) de taper crontab -r en pensant taper crontab -e, et d'effacer instantanément 100 lignes de tâches planifiées.
Bonne Pratique (Alias de Sécurité)
Pour éviter cela, beaucoup d'admins ajoutent un "alias" de sécurité dans leur .bashrc / .zshrc :
# (Ajouter ceci à ~/.bashrc) # (Demande une confirmation (interactive) avant de 'remove') alias crontab='crontab -i'
(L'option -i (interactive) demande une confirmation "yes/no" avant -r).
$PATH)C'est le piège n°1 du dépannage cron. ("Le script marche quand je le lance à la main, mais échoue dans cron !").
Le Problème
Votre shell (Bash/Zsh) (via .bashrc) a un $PATH riche : /usr/local/bin:/usr/bin:/bin:/home/user/bin
Le daemon crond s'exécute avec un $PATH minimaliste (défini par pam_env) : /usr/bin:/bin
Exemple (Échec)
# (Le script '/usr/local/bin/mon_script_node' # a été installé via 'npm install -g') * * * * * mon_script_node # (Résultat : Échec. Cron ne trouve pas 'mon_script_node' # dans /usr/bin ou /bin)
Solutions (Par ordre de préférence)
- (Meilleur) Chemins Absolus (dans le cron) :
* * * * * /usr/local/bin/mon_script_node - (OK) Chemins Absolus (dans le script) :
(Simon_script.shappellenode-> utiliser/usr/local/bin/node). - (OK) Définir le
PATH(en haut du crontab) :PATH=/usr/bin:/bin:/usr/local/bin * * * * * mon_script_node
Par défaut, cron capture tout ce qui est écrit sur stdout (sortie standard) et stderr (sortie d'erreur), et essaie de l'envoyer par email (voir 5.3) à l'utilisateur.
C'est souvent indésirable (spam, ou le service mail n'est pas configuré).
Contrôler la Sortie (Redirection Shell)
Scénario 1 : Silence Total (Le "Trou Noir")
Utilisé en production (si on est sûr que ça marche) pour éviter tout log/email.
# (Redirige stdout (1) vers /dev/null) # (Redirige stderr (2) vers la même destination (1)) * * * * * /path/to/script.sh > /dev/null 2>&1
Scénario 2 : Logger dans un Fichier (Recommandé)
Rediriger stdout et stderr dans un fichier de log (avec rotation, ex: logrotate).
# 1. Envoyer stdout et stderr au même fichier (Append) * * * * * /path/to/script.sh >> /var/log/mon_script.log 2>&1 # 2. Séparer stdout et stderr * * * * * /path/to/script.sh >> /var/log/mon_script.log 2>> /var/log/mon_script.err
MAILTO)MAILTO est une variable d'environnement spéciale, définie en haut du fichier crontab.
Scénario 1 : Désactiver tous les Emails (Recommandé)
Si MAILTO est vide (""), aucun email ne sera envoyé, même si les commandes (stdout/stderr) produisent une sortie.
MAILTO="" # (Toutes les sorties de tous les jobs # ci-dessous sont envoyées à /dev/null) * * * * * /path/to/script.sh
Scénario 2 : Centraliser les Emails
Envoyer toutes les sorties (erreurs, logs) à une adresse spécifique (ex: un admin) plutôt qu'à l'utilisateur local (ex: www-data).
MAILTO="admin@ideolab.com" # (Toute sortie (stdout/stderr) de ce job # sera envoyée à admin@ideolab.com) */15 * * * * /path/to/check.sh
C'est la méthode "standard" pour un utilisateur (ou un service, ex: www-data) pour gérer ses propres tâches.
- Commande :
crontab -e(ousudo crontab -e -u www-data) - Emplacement (Debian/Ubuntu) :
/var/spool/cron/crontabs/[nom_utilisateur] - Format : Standard (5 champs + commande).
- Permissions : S'exécute avec les permissions de l'utilisateur (ex:
www-data).
/etc/crontab)C'est le fichier de configuration "maître" du système. Il ne doit pas être édité avec crontab -e, mais avec nano /etc/crontab.
Différence : Le 6ème Champ (Utilisateur)
Les crontabs système (/etc/crontab et /etc/cron.d/) ont un champ supplémentaire (obligatoire) entre le "Temps" et la "Commande" : l'Utilisateur (User) qui doit exécuter la tâche.
# (m h dom mon dow) [USER] [COMMAND] # Syntaxe /etc/crontab (Notez 'root') 17 * * * * root cd / && run-parts --report /etc/cron.hourly 25 6 * * * root test -x /usr/sbin/anacron || ...
/etc/cron.d/ (Drop-in)C'est la meilleure pratique (moderne) pour les applications (paquets) qui doivent ajouter des tâches système.
Au lieu de modifier le /etc/crontab (risqué), un paquet (ex: certbot) "droppe" (dépose) son propre fichier de configuration dans /etc/cron.d/.
crond lit /etc/crontab ET tous les fichiers dans /etc/cron.d/.
Exemple (/etc/cron.d/certbot)
# (Fichier installé par 'apt install certbot') # (Syntaxe identique à /etc/crontab (avec "user")) SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl ...
cron.daily, cron.weekly, etc.Ce sont de simples dossiers (/etc/cron.daily, /etc/cron.weekly...). Ils ne sont pas un mécanisme cron magique.
Fonctionnement (run-parts)
Ils sont gérés (déclenchés) par /etc/crontab (ou anacron) via la commande run-parts.
Regardez /etc/crontab :
# (Extrait de /etc/crontab) # (À 6h25, tous les jours, 'root' exécute 'run-parts' # sur le dossier 'cron.daily') 25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
Usage : Pour ajouter un script "daily" (ex: logrotate, backup), il suffit de le copier (en chmod +x) dans /etc/cron.daily/. (Simple, mais pas de contrôle sur l'heure exacte (ce sera 6h25)).
anacron (Pour PC Portables)Problème : cron (le daemon) est "stupide". Si le PC est éteint à 6h25 (l'heure de cron.daily), les tâches (backups, updates) sont manquées (skipped) et ne s'exécuteront que le lendemain à 6h25.
Solution (anacron)
anacron (Anachronistic Cron) est un "complément" à cron, conçu pour les machines non-24/7 (Desktops, Laptops).
Fonctionnement (/etc/anacrontab) :
anacronest lancé au démarrage (boot) (ou viacron.hourly).- Il vérifie un "timestamp" (tampon) : "Quand ai-je exécuté
cron.dailyla dernière fois ?". - (Ex: "Il y a 30 heures").
- Si le temps est > 1 jour, il exécute immédiatement les tâches
cron.daily(rattrapage).
(Sur les systèmes Desktop (Ubuntu), anacron gère cron.daily/weekly/monthly, et /etc/crontab est (presque) vide).
# Syntaxe : m h dom mon dow commande # (m=Minute, h=Heure, dom=JourMois, mon=Mois, dow=JourSemaine) # --- Exemples de Temps --- # Toutes les minutes * * * * * ... # Toutes les 5 minutes */5 * * * * ... # Toutes les 15 minutes (alternative) 0,15,30,45 * * * * ... # Toutes les heures, à la 30e minute (ex: 10:30, 11:30) 30 * * * * ... # Tous les jours à 2h00 du matin 0 2 * * * ... # Tous les jours à 5h30 30 5 * * * ... # Tous les Lundis à 4h00 du matin 0 4 * * 1 ... (1 = Lundi, 0/7 = Dimanche) # Tous les 1er du mois à 00h00 0 0 1 * * ... # Pendant les heures de bureau (8h-17h), # les jours de semaine (Lun-Ven) * 8-17 * * 1-5 ... # --- Chaînes Spéciales --- @reboot /path/to/script.sh @hourly /path/to/script.sh @daily /path/to/script.sh @weekly /path/to/script.sh @monthly /path/to/script.sh # --- Logs & Commandes --- MAILTO="" # (Désactive les emails) PATH=/usr/bin:/bin:/usr/local/bin # (Définit un PATH) # Exécuter un script (silencieux) * * * * * /usr/bin/php /var/www/cron.php > /dev/null 2>&1 # Exécuter un script (avec logs) * * * * * /path/to/backup.sh >> /var/log/backup.log 2>&1 # /etc/crontab (Syntaxe Système - avec "user") * * * * * root /path/to/script_root.sh * * * * * www-data /path/to/script_www.sh
