Tutoriel

Crontab : exemples de planification de tâches sous Linux, syntaxe et erreurs courantes

Mis à jour: · Skillaria.Top

Crontab est la table de planification que le démon cron utilise pour lancer des commandes : chaque ligne comporte cinq champs temporels (minute, heure, jour du mois, mois, jour de la semaine) suivis de la commande. Par exemple, */5 * * * * /opt/backup.sh lance le script toutes les 5 minutes. On édite la table avec crontab -e ; la plupart des problèmes viennent de l'environnement réduit de cron : indiquez les chemins complets et redirigez la sortie vers un journal.

Cron est le planificateur de tâches standard de Linux : le démon cron lit chaque minute les tables de planification (crontab) et lance les commandes dont l'heure est arrivée. C'est ainsi que l'on effectue les sauvegardes nocturnes, nettoie les fichiers temporaires, renouvelle les certificats ou envoie des rapports. Vous trouverez ci-dessous la syntaxe, des exemples de crontab pour les cas courants et l'analyse des erreurs qui font qu'une tâche ne s'exécute pas « en silence ».

Ouvrir et modifier une crontab

Chaque utilisateur possède sa propre table. On la gère avec la commande crontab, et non en modifiant directement les fichiers de /var/spool/cron :

CommandeCe qu'elle fait
crontab -eouvrir votre table dans un éditeur (au premier lancement, il vous demande de choisir l'éditeur)
crontab -lafficher la table actuelle
crontab -rsupprimer la table entière, sans confirmation
crontab -i -rsupprimer avec confirmation (Debian/Ubuntu, RHEL)
sudo crontab -u alice -emodifier la table d'un autre utilisateur
crontab fichierremplacer la table par le contenu d'un fichier

Après enregistrement, crontab -e vérifie la syntaxe et affiche crontab: installing new crontab. Si une ligne est erronée, vous verrez errors in crontab file, can't install et on vous proposera de rééditer. Il n'est pas nécessaire de redémarrer le démon : les modifications sont prises en compte automatiquement.

Prudence avec -r : les touches e et r sont voisines sur le clavier, et il n'existe aucune copie de sauvegarde de la table. Prenez l'habitude de faire une copie :

crontab -l > ~/crontab.bak
# restaurer
crontab ~/crontab.bak

Syntaxe de la crontab : cinq champs temporels

Chaque ligne de tâche se présente ainsi :

# ┌───────── minute (0–59)
# │ ┌─────── heure (0–23)
# │ │ ┌───── jour du mois (1–31)
# │ │ │ ┌─── mois (1–12 ou jan–dec)
# │ │ │ │ ┌─ jour de la semaine (0–7 ou sun–sat ; 0 et 7 — dimanche)
# │ │ │ │ │
  * * * * * commande

Chaque champ peut utiliser des caractères spéciaux :

CaractèreSignificationExemple
*toute valeur* * * * * — chaque minute
,liste0 9,18 * * * — à 9h00 et à 18h00
-intervalle0 9-18 * * * — chaque heure de 9h à 18h
/pas*/15 * * * * — toutes les 15 minutes

Le pas peut se combiner avec un intervalle : 0 8-20/2 * * * — toutes les deux heures de 8h à 20h (8, 10, …, 20). L'heure est celle du fuseau horaire du système : vérifiez-la avec timedatectl.

Exemples de crontab pour chaque jour

PlanificationLigne crontab
chaque minute* * * * *
toutes les 5 minutes*/5 * * * *
toutes les 30 minutes*/30 * * * * ou 0,30 * * * *
chaque heure, en début d'heure0 * * * *
toutes les 6 heures0 */6 * * *
chaque jour à 3h000 3 * * *
chaque jour à 23h4545 23 * * *
les jours ouvrés à 9h000 9 * * 1-5
les week-ends à midi0 12 * * 6,0
les lundis à 8h3030 8 * * 1
le 1er de chaque mois à 00h000 0 1 * *
une fois par trimestre0 0 1 1,4,7,10 *
une fois par an, le 1er janvier0 0 1 1 *
toutes les 10 minutes pendant les heures de bureau*/10 9-18 * * 1-5

Une ligne complète se compose de la planification suivie de la commande :

# sauvegarde de la base chaque nuit à 3h00
0 3 * * * /usr/local/bin/db-backup.sh >> /var/log/db-backup.log 2>&1

# nettoyage des fichiers temporaires de plus de 7 jours, le dimanche
0 4 * * 0 /usr/bin/find /tmp/app -type f -mtime +7 -delete

# contrôle du site toutes les 5 minutes
*/5 * * * * /usr/bin/curl -fsS https://example.com/health > /dev/null || /usr/local/bin/alert.sh

Raccourcis @reboot, @daily et autres

Au lieu de cinq champs, on peut écrire un raccourci :

RaccourciÉquivalent
@rebootune seule fois au démarrage du démon cron (après le boot du système)
@hourly0 * * * *
@daily / @midnight0 0 * * *
@weekly0 0 * * 0
@monthly0 0 1 * *
@yearly / @annually0 0 1 1 *
@reboot /home/alice/bin/start-tunnel.sh >> /home/alice/tunnel.log 2>&1

Pour un service qui doit tourner en permanence et redémarrer après un arrêt inattendu, @reboot est une solution faible : mieux vaut une unité systemd avec Restart=on-failure.

Lancer une tâche toutes les N secondes

L'unité minimale de cron est la minute. Pour aller plus vite, deux techniques existent. La première consiste à ajouter des lignes décalées avec sleep :

* * * * * /opt/check.sh
* * * * * sleep 30; /opt/check.sh

La seconde, plus propre, est un timer systemd avec OnUnitActiveSec=30s. Si une tâche doit s'exécuter plus d'une fois par minute, il s'agit en général d'un travail pour un démon ou un timer, et non pour cron.

Crontab système : /etc/crontab et /etc/cron.d

Outre les tables utilisateur, il existe des tables système. Leur format diffère : entre l'heure et la commande figure le nom de l'utilisateur sous lequel la commande doit être lancée.

# /etc/cron.d/certbot-renew
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

0 */12 * * * root certbot renew --quiet

Emplacements :

  • /etc/crontab — la table système principale ; sous Debian/Ubuntu, elle lance les répertoires ci-dessous.
  • /etc/cron.d/ — fichiers séparés contenant des tâches, pratiques à déposer via les paquets ou avec Ansible.
  • /etc/cron.hourly/, cron.daily/, cron.weekly/, cron.monthly/ — on y place des scripts exécutables sans planification ; ils sont lancés par run-parts (ou anacron).

Piège de run-parts : sous Debian et Ubuntu, il ignore les fichiers dont le nom contient un point. Le script backup.sh placé dans /etc/cron.daily/ ne sera pas exécuté : nommez-le backup. Pour vérifier ce qui sera exécuté, utilisez run-parts --test /etc/cron.daily.

Les fichiers de /etc/cron.d/ doivent appartenir à root, ne pas être accessibles en écriture au groupe ou aux autres, et se terminer par un saut de ligne, sinon cron les ignore.

Environnement de cron : PATH, SHELL et variables

La cause principale de la phrase « ça marche dans le terminal, mais pas dans cron » est l'environnement. Cron lance les commandes via /bin/sh, sans charger votre .bashrc ni votre .profile, et avec un PATH minimal (généralement /usr/bin:/bin). Ainsi, docker, node ou php installés dans /usr/local/bin peuvent tout simplement être introuvables.

On peut définir des variables en tête de la table :

SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=admin@example.com
CRON_TZ=Europe/Paris

0 6 * * * cd /srv/app && ./report.sh
  • MAILTO — destinataire de la sortie de la tâche ; MAILTO="" désactive l'envoi de courriels.
  • CRON_TZ — fuseau horaire de la planification (pris en charge par cronie sur RHEL/Fedora ; la version de cron de Debian ne gère pas cette variable).
  • Les substitutions comme $HOME/bin dans les valeurs de variables ne fonctionnent pas : écrivez les chemins en entier.

La solution la plus fiable consiste à indiquer dans la tâche des chemins absolus vers tous les programmes et fichiers, et à mettre en première ligne de chaque script le shebang : #!/bin/bash.

Où consulter les journaux de cron

Cron journalise le fait qu'une tâche a été lancée, mais pas sa sortie :

# Debian/Ubuntu
grep CRON /var/log/syslog
# via journald (systemd)
journalctl -u cron --since today      # Debian/Ubuntu
journalctl -u crond --since today     # RHEL, Fedora, Rocky
# RHEL sans journald
tail -f /var/log/cron

La ligne de lancement ressemble à ceci :

Oct 14 03:00:01 web1 CRON[21544]: (root) CMD (/usr/local/bin/db-backup.sh >> /var/log/db-backup.log 2>&1)

Pour voir ce que la tâche a affiché et l'erreur qui l'a fait échouer, redirigez à la fois stdout et stderr vers un fichier : >> /var/log/job.log 2>&1. Sans cela, la sortie part par courriel local, et si aucun agent de messagerie n'est installé, elle est perdue (le journal affiche alors No MTA installed, discarding output).

Pourquoi cron ne lance pas la tâche : erreurs courantes

Commande introuvable

Symptôme : command not found dans le journal de la tâche. Cause : un PATH réduit. Solution : le chemin complet du programme (la commande which docker le donne) ou une ligne PATH= en tête de la table.

Caractère pourcent dans la commande

Dans une crontab, le caractère % signifie un saut de ligne : tout ce qui suit le premier % est transmis à la commande sur son entrée standard. C'est pourquoi la ligne classique avec une date dans le nom de fichier casse :

# incorrect — la commande est tronquée au premier %
0 2 * * * tar czf /backup/site-$(date +%F).tar.gz /var/www
# correct — échapper le %
0 2 * * * tar czf /backup/site-$(date +\%F).tar.gz /var/www

Plus simple encore : placer la logique dans un script, où le % ne doit pas être échappé.

Script non exécutable ou avec de mauvais retours à la ligne

L'erreur Permission denied signifie que le fichier n'a pas le bit x : exécutez chmod +x script.sh, ou lancez-le explicitement avec /bin/bash /opt/script.sh. Si le script a été écrit sous Windows, les fins de ligne CRLF provoquent l'erreur étrange /bin/bash^M: bad interpreter : corrigez-les avec sed -i 's/\r$//' script.sh ou dos2unix.

Chemins relatifs et répertoire de travail

La tâche démarre dans le répertoire personnel de l'utilisateur. Si le script lit ./config.ini, il le cherchera dans ~. Ajoutez cd /srv/app && avant la commande, ou utilisez des chemins absolus dans le script.

Jour du mois et jour de la semaine en même temps

Lorsque les deux champs sont renseignés, cron se déclenche dès que l'une ou l'autre condition est remplie, et non les deux à la fois. La ligne 0 9 13 * 5 s'exécute le 13 du mois et chaque vendredi, et non uniquement le vendredi 13. Il faut alors vérifier la condition dans la commande :

0 9 13 * * [ "$(date +\%u)" = 5 ] && /opt/friday13.sh

Tâches qui se chevauchent

Si une sauvegarde dure plus longtemps que l'intervalle, la suivante démarre par-dessus la précédente. La protection consiste à utiliser un verrou avec flock :

*/10 * * * * /usr/bin/flock -n /tmp/sync.lock /opt/sync.sh

Avec l'option -n, la seconde instance se termine immédiatement si la première est encore en cours.

Le démon cron ne tourne pas

Vérifiez avec systemctl status cron (sur RHEL, le service s'appelle crond). Dans les images minimales, par exemple les conteneurs Docker, le démon cron est absent : personne n'exécute alors les tâches de la crontab.

Déboguer une tâche cron

Lancez la commande dans un environnement aussi proche que possible de celui de cron :

env -i SHELL=/bin/sh PATH=/usr/bin:/bin HOME=$HOME /bin/sh -c '/opt/backup.sh'

Si une erreur survient ici, elle surviendra aussi dans cron. Pour un test, planifiez temporairement * * * * *, redirigez la sortie vers un fichier et suivez-le avec tail -f. Les calculateurs en ligne d'expressions cron aident à vérifier la planification, mais le dernier mot revient au journal du système.

Qui peut utiliser cron : cron.allow et cron.deny

L'accès est restreint par les fichiers /etc/cron.allow et /etc/cron.deny. Si cron.allow existe, seuls les utilisateurs qui y sont listés peuvent utiliser crontab. Sinon, si seul cron.deny existe, tout le monde peut l'utiliser sauf les utilisateurs listés. Un utilisateur bloqué qui lance crontab -e reçoit le message You (bob) are not allowed to use this program.

Conclusion

Une crontab, ce sont des lignes de cinq champs temporels suivis d'une commande : */5 * * * * — toutes les 5 minutes, 0 3 * * * — chaque nuit, 0 9 * * 1-5 — les jours ouvrés. Modifiez la table avec crontab -e, utilisez des chemins absolus, échappez le %, journalisez la sortie et protégez les tâches longues avec flock. Ces exemples suffisent pour la plupart des tâches serveur, et l'automatisation et la planification sont détaillées en pratique dans le cours Linux.

Questions fréquentes

En quoi cron diffère-t-il d'anacron ?

Cron lance les tâches à l'heure exacte et les manque si l'ordinateur était éteint. Anacron garantit que les tâches quotidiennes, hebdomadaires et mensuelles seront exécutées après le démarrage, ce qui le rend adapté aux ordinateurs portables et aux postes de bureau.

Faut-il préférer cron ou les timers systemd ?

cron est plus simple et disponible presque partout. Les timers systemd fournissent des journaux via journalctl, des dépendances, une limitation des ressources et l'option Persistent=true pour rattraper les exécutions manquées ; c'est pourquoi on les privilégie de plus en plus sur les serveurs modernes pour les tâches importantes.

Où est physiquement stockée la crontab d'un utilisateur ?

Sous Debian et Ubuntu, dans /var/spool/cron/crontabs/nom ; sous RHEL et Fedora, dans /var/spool/cron/nom. Il ne faut pas modifier ces fichiers directement : utilisez crontab -e.

Comment désactiver temporairement une tâche de la crontab ?

Ajoutez le caractère # au début de la ligne via crontab -e. Pour désactiver toutes les tâches d'un utilisateur, enregistrez la table dans un fichier avec crontab -l, puis supprimez-la avec crontab -r.

Comment lancer une tâche le dernier jour du mois ?

Il n'existe pas de champ prévu pour cela. Planifiez la tâche les 28 à 31 du mois et vérifiez que le lendemain est le 1er : 0 23 28-31 * * [ "$(date -d tomorrow +\%d)" = 01 ] && /opt/job.sh.

Apprenez ce sujet en vidéo

Ce sujet est traité en détail avec de la pratique dans le cours « Linux: с нуля до уверенного администрирования ».

Voir le cours