Crontab : planifier des exécutions sous Linux
Sous Linux, cron est le service qui exécute des commandes à des moments prévus : une sauvegarde chaque nuit, un script toutes les 5 minutes, un nettoyage chaque semaine. Les tâches à exécuter sont décrites dans un fichier appelé crontab, à raison d'une tâche par ligne.
Gérer sa crontab
Chaque utilisateur a sa propre crontab, qui s'exécute avec ses droits. Les commandes suivantes la gèrent :
crontab -e # édite la crontab (ouvre l'éditeur par défaut) crontab -l # affiche la crontab crontab -r # supprime toute la crontab, sans confirmation
Faites attention à crontab -r : la touche r est voisine de e, et la suppression est immédiate. Sauvegardez régulièrement votre crontab avec crontab -l > crontab.sauvegarde (vous la restaurerez avec crontab crontab.sauvegarde). Sur la plupart des distributions, crontab -i -r demande une confirmation avant de supprimer.
En tant que root, l'option -u permet de gérer la crontab d'un autre utilisateur : sudo crontab -u www-data -e.
Format d'une ligne
Une ligne contient cinq champs de planification, séparés par des espaces, suivis de la commande :
minute heure jour_du_mois mois jour_de_la_semaine commande
| Champ | Valeurs autorisées |
|---|---|
| Minute | 0 à 59 |
| Heure | 0 à 23 |
| Jour du mois | 1 à 31 |
| Mois | 1 à 12 (ou jan, feb, mar…) |
| Jour de la semaine | 0 à 7 (0 et 7 = dimanche, 1 = lundi), ou sun, mon, tue… |
Chaque champ accepte, en plus d'une valeur simple, les notations suivantes :
| Notation | Signification | Exemple |
|---|---|---|
* | toutes les valeurs possibles | * * * * * : chaque minute |
, | liste de valeurs | 0,30 : aux minutes 0 et 30 |
- | plage de valeurs | 1-5 : du lundi au vendredi |
/ | un pas | */5 : toutes les 5 minutes ; 8-18/2 : de 8 h à 18 h, une heure sur deux |
Exemples
# Toutes les 5 minutes, en gardant une trace dans un fichier de log */5 * * * * /usr/bin/php /home/admin/www/script.php param1 param2 >> /home/admin/www/logs/script.log 2>&1 # Tous les jours à 3 h 30 30 3 * * * /home/admin/bin/sauvegarde.sh # Du lundi au vendredi à 18 h 0 18 * * 1-5 /home/admin/bin/rapport.sh # À minuit chaque jour de travail de la semaine 0 0 * * 1-5 /usr/bin/php /home/admin/www/script.php # Toutes les 15 minutes, de 8 h à 18 h, en semaine */15 8-18 * * 1-5 /home/admin/bin/synchro.sh # Toutes les 2 heures, à l'heure pile 0 */2 * * * /home/admin/bin/nettoyage.sh # Le 1er de chaque mois à minuit 0 0 1 * * /home/admin/bin/facturation.sh # Le 1er janvier à minuit, chaque année 0 0 1 1 * /usr/bin/php /home/admin/www/happyNewYear.php
Les raccourcis
Les versions courantes de cron acceptent aussi des mots-clés à la place des cinq champs :
| Raccourci | Équivalent | Signification |
|---|---|---|
@reboot | (aucun) | une fois, au démarrage du service cron |
@hourly | 0 * * * * | chaque heure |
@daily ou @midnight | 0 0 * * * | chaque jour à minuit |
@weekly | 0 0 * * 0 | chaque dimanche à minuit |
@monthly | 0 0 1 * * | le 1er de chaque mois à minuit |
@yearly ou @annually | 0 0 1 1 * | le 1er janvier à minuit |
@reboot /home/admin/bin/demarrage.sh
Les pièges à connaître
La commande ne s'exécute pas comme dans votre terminal
Cron lance les commandes avec un environnement minimal : un PATH réduit (souvent /usr/bin:/bin), le shell /bin/sh et aucun des réglages de votre .bashrc. Une commande qui marche dans votre terminal peut donc échouer avec « command not found » ou ne pas trouver ses fichiers. Pour l'éviter :
- utilisez toujours des chemins absolus :
/usr/bin/phpet nonphp(which phpdonne le chemin),/home/admin/script.shet non./script.sh; - déclarez des variables en tête de crontab, elles s'appliquent à toutes les lignes qui suivent :
SHELL=/bin/bash PATH=/usr/local/bin:/usr/bin:/bin MAILTO=admin@example.com 0 3 * * * /home/admin/bin/sauvegarde.sh
- assurez-vous que le script est exécutable (
chmod +x script.sh) et commence par un shebang (#!/bin/bash).
Où va le résultat de la commande ?
Tout ce que la commande affiche (sortie et erreurs) est envoyé par e-mail à l'utilisateur, ou à l'adresse définie par MAILTO, si le serveur sait envoyer du courrier. Sinon, ce message est perdu. Choisissez donc explicitement :
# Garder la sortie et les erreurs dans un fichier de log 0 3 * * * /home/admin/bin/sauvegarde.sh >> /var/log/sauvegarde.log 2>&1 # Ne rien garder 0 3 * * * /home/admin/bin/sauvegarde.sh > /dev/null 2>&1
Écrivez MAILTO="" en tête de crontab pour désactiver complètement l'envoi d'e-mails.
Le caractère %
Dans une ligne de crontab, un % non protégé est interprété comme un retour à la ligne : la commande est coupée à cet endroit. Il faut le faire précéder d'un antislash, par exemple pour une date dans un nom de fichier :
0 3 * * * /usr/bin/mysqldump ma_base > /home/admin/sauvegardes/ma_base_$(date +\%F).sql
Jour du mois et jour de la semaine
Si vous renseignez à la fois le jour du mois et le jour de la semaine, la commande s'exécute quand l'un ou l'autre correspond, et non quand les deux correspondent. 0 0 13 * 5 s'exécute donc tous les 13 du mois et tous les vendredis, pas seulement les vendredis 13. Pour ce cas, planifiez le vendredi et testez la date dans la commande.
Les tâches qui se chevauchent
Cron ne vérifie pas si l'exécution précédente est terminée. Si un script lancé toutes les minutes dure parfois plus d'une minute, plusieurs copies tournent en même temps. L'outil flock empêche cela : la nouvelle exécution est abandonnée tant que la précédente tient le verrou.
* * * * * /usr/bin/flock -n /tmp/synchro.lock /home/admin/bin/synchro.sh
Précision, fuseau horaire et autres détails
- La précision de cron est d'une minute. Pour exécuter une commande toutes les 30 secondes, utilisez deux lignes, dont une retardée :
* * * * * commandeet* * * * * sleep 30; commande. - Les heures sont celles du fuseau horaire du serveur (
timedatectll'affiche). Sur un serveur en UTC, « 3 h » n'est pas 3 h en France. - Autour du changement d'heure, une tâche programmée entre 2 h et 3 h peut s'exécuter deux fois ou pas du tout selon la version de cron : évitez cette plage pour les tâches importantes.
- Terminez le fichier par un retour à la ligne : une dernière ligne qui n'en a pas peut être ignorée.
Les crontabs du système
En plus des crontabs des utilisateurs, le système a les siennes, modifiables par root :
/etc/crontabet les fichiers du dossier/etc/cron.d/ont un sixième champ, l'utilisateur qui exécute la commande, placé avant la commande :
*/10 * * * * www-data /usr/bin/php /var/www/script.php
- Les dossiers
/etc/cron.hourly,/etc/cron.daily,/etc/cron.weeklyet/etc/cron.monthlycontiennent des scripts exécutés à la fréquence indiquée par le nom du dossier, sans écrire de ligne de crontab. Sur Debian et Ubuntu, le script doit être exécutable et son nom ne doit pas contenir de point :sauvegardesera exécuté,sauvegarde.shsera ignoré.
Les fichiers /etc/cron.allow et /etc/cron.deny permettent de restreindre les utilisateurs qui ont le droit d'utiliser crontab : s'il existe, cron.allow liste les seuls utilisateurs autorisés.
Vérifier que la tâche s'exécute
Si rien ne se passe, vérifiez dans l'ordre :
- Le service tourne. Il s'appelle
cronsur Debian et Ubuntu,crondsur Red Hat, CentOS et Fedora :systemctl status cron. - La ligne a été lue et lancée. Les journaux le disent :
grep CRON /var/log/syslog(Debian, Ubuntu),journalctl -u cron(avec systemd) ou/var/log/cron(Red Hat). - La commande marche seule, avec l'utilisateur concerné et un environnement vide. Pour s'approcher de celui de cron :
env -i HOME="$HOME" PATH=/usr/bin:/bin /bin/sh -c '/home/admin/bin/sauvegarde.sh'. - La sortie contient l'erreur. Redirigez-la vers un fichier de log comme vu plus haut, le temps de comprendre le problème.
Pour aller plus loin
- Lancer une page web depuis la crontab
- Linux : démarrage automatique des services
- crontab.guru : un site qui traduit une expression cron en phrase, pour vérifier une planification avant de l'utiliser.
- La documentation complète du format :
man 5 crontab.