---
categories: sysadmin web
title: Howto Cron
...

Le service **cron** (diminutif de *crontab*, pour **c**h**ron**o **tab**le) est le planificateur de tâches standard sur les systèmes UNIX/Linux. Il permet le déclenchement de commandes à des dates récurrentes et à la minute près.

# Installation

Très souvent, on le retrouve déjà installé :

~~~
# systemctl status cron
● cron.service - Regular background program processing daemon
   Loaded: loaded (/lib/systemd/system/cron.service; enabled; vendor preset: enabled)
     Docs: man:cron(8)
 Main PID: 492 (cron)
   CGroup: /system.slice/cron.service
           └─492 /usr/sbin/cron -f
~~~

Sinon, la commande suivante permet de l'obtenir :

~~~
apt install cron
~~~

# Configuration

Les paramètres principaux sont définit dans le fichier `/etc/crontab` :

~~~
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
~~~

On observe que :

  - Le shell par défaut sera /bin/sh
  - Les tâches crons auront un accès facilité à l'ensemble de répertoires où se trouvent les programmes exécutables.
  - Des dates sont définies pour exécuter des actions inclus dans les répertoires dédiés `/etc/cron.*`.

D'autres options de configurations peuvent être pris en charge par défaut pour toutes les tâches crons via le fichier `/etc/default/cron`. Notamment en ce qui concerne le niveau de verbosité de la journalisation, définir des variables d'environnements, etc.

# Cas d'usage

## Les dossiers /etc/cron.* et /etc/cron.d/

Pour lancer un script à **une date précise** : il suffit de le rendre exécutable et de le placer dans l'un des répertoires `/etc/cron.*` en fonction de la fréquence souhaitée.

Pour lancer un script à **une fréquence personnalisée** : il suffit de créer un nouveau fichier pour le placer dans `/etc/cron.d/` incluant une suite de paramètres pour indiquer la fréquence et l'utilisateur qui doit lancer la commande, par exemple :

~~~
30 05 * * 0 www-data /usr/local/adm/savelog
~~~

> Attention : En cas d'erreur de syntaxe dans un script, toutes les autres tâches crons du même répertoire ne seront pas lancés ! Il faut donc réserver cette utilisation à des scripts bien vérifiés!

> Attention : Les noms de scripts contenant des points sont ignorés. Cette particularité est utile pour désactiver un script en ajoutant .disabled comme extension.


## La commande crontab

Cette commande permet d’éditer/lister/supprimer les tâches planifiées gérées par le service cron et sont automatiquement liées à des comptes utilisateurs. Elles sont conservées dans /var/spool/cron/. L'avantage de cette commande est la vérification syntaxique en quittant l'éditeur.

Pour ajouter une tâche cron :

~~~
crontab -e
~~~

> Attention : Méfiez-vous de la touche "r" qui est proche de la touche "e" sur un clavier Azerty ou Qwerty où `crontab -r` efface définitivement toute votre crontab!

Pour lister les tâches cron :

~~~
crontab -l
~~~


## La syntaxe

> **Attention: La syntax des fichiers dans `/etc/cron.d/` est différente et nécessite un nom d'utilisateur entre le temps d'exécution et la commande.**

On peut s'aider de [crontab guru](https://crontab.guru/) pour être sûr de ne pas faire d'erreur sur l'horaire.

Plus en détail, la syntaxe complète est :

~~~
minutes heures jours mois jour/semaine commande
~~~

On peut utiliser `*` pour toutes les occurrences (tous les jours, ou toutes les heures, etc.). On peut également utiliser des listes à virgule (`3,5,7`) ainsi des intervalles (`2-6`) ; on peut aussi avoir des intervalles réguliers (`*/15`).

Exemples de crontab :

~~~
0,30,45,51 * * * * /usr/local/adm/send-data
*/15 * * * * /usr/local/adm/check-nis 1>/dev/null 2>&1
00 01 * * * nice -10 find /inf -name core -exec rm -f {} \;
10 03 * * 1-6 nice -10 /usr/local/adm/sauvegarde-daily
30 05 * * 0 /usr/local/adm/savelog-weekly
30 06 1 * * /usr/local/adm/savelog-monthly
00 00 1 1 * /usr/local/bin/happy-new-year
@daily /usr/local/bin/minuit-check
~~~

On peut utiliser les mots clés `@hourly`/`@daily`/`@weekly`/`@monthly` pour lancer à la première minute de chaque heure/jour/semaine/mois (à ne pas confondre avec les répertoires /etc/cron.* qui sont lancés à des dates particulières).

Pour plus de détails sur les recommandations sur l'écriture de scripts à mettre en crontab voir [TipsDevWeb#scripts-en-crontab]().

## Les Variables

Plusieurs variables peuvent être utilisées dans une crontab :

`PATH` : redéfinir le PATH des commandes lancés

`SHELL` : remplacer le shell /bin/sh utilisé par défaut par /bin/bash par exemple

`MAILTO` : Un email est envoyé à l'utilisateur lorsqu'une commande génère une sortie (stdout/stderr). On peut changer le destinataire ainsi qu'en mettre plusieurs ou empêcher l'envoi d'un message avec `MAILTO=""`.

Ces variables peuvent être définies plusieurs fois, notamment `MAILTO` qui pourra précéder chaque ligne de cron :

~~~
MAILTO=jdoe@example.com,alert@example.com
@daily df -h
MAILTO=""
@hourly systemctl restart javajob
MAILTO=alert@example.com
@weekly /usr/local/bin/security-check
~~~

# log2mail

On peut ajouter la configuration suivante au logiciel log2mail pour détecter d'éventuelles erreurs de syntaxe :

~~~
file = /var/log/cron.log
  pattern = "Error"
  mailto = root
~~~

# FAQ

## Peut-on écrire un cron dans /etc/crontab ?

Si l'on a joute une ligne de cron, elle sera exécutée par Root mais on déconseille fortement cette utilisation car:

  - Ce fichier de configuration doit rester intact autant que possible pour faciliter les mises à jour du système.
  - On évite autant que l'on peut de lancer un cron en tant que _root_ par principe de sécurité.
  - La moindre erreur de syntaxe provoquera la non-exécution de tous les autres scripts !

## Changement d'heure

Lors d'un changement d'heure d'été ou d'hiver en France où un script est planifié pour être exécuté entre 2h et 3h du matin, il peut être lancé deux fois! Le service cron sait détecter ce souci mais par précaution, on évite d'en établir durant cette tranche horaire.

## Échappement de caractères

Prenons l'exemple d'une copie horodatée de /etc chaque heure :

~~~
@hourly root tar -cf /home/backup/etc-$(date +%H).tar /etc
~~~

Celle-ci **ne sera pas exécutée** car le caractère `%` est interprété comme un saut de ligne où la commande sera incomplète et donc non fonctionnelle.

La correction s'applique en **échappant** le `%` avec un `\` :

~~~
@hourly root tar -cf /home/backup/etc-$(date +\%H).tar /etc
~~~