DOC:UNIX:Crontab

De MonPtitSite
Sauter à la navigation Sauter à la recherche
Accueil SysAdmin Hobbies                  

crontab

crontab est le nom du programme sous Unix (et Linux) qui permet d'éditer des tables de configuration du programme cron. Ces tables spécifient les tâches à exécuter et leur horaire d'exécution avec éventuellement une périodicité. Par extension, on appelle souvent cron (ou cron job en anglais) toute tâche lancée à horaire périodique.

Fonctionnement

La commande crontab modifie un fichier relatif à l'utilisateur. Par sécurité, crontab vérifie la syntaxe avant de mettre à jour le fichier. Ce fichier se situe dans l'arborescence /var, par exemple :

Ainsi pour l'utilisateur root sur une machine Debian, la table cron sera stockée dans /var/spool/cron/crontabs/root

La majorité des systèmes Linux (SuSE, Debian, Red Hat) disposent en plus d'une table cron centralisée dans /etc/crontab.

On trouve également des dossiers /etc/cron.d, /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly et /etc/cron.monthly qui contiennent les tables cron des différentes parties du système (rotation des journaux, mise à jour de fichiers...).

Pour les postes de travail qui ne fonctionnent pas forcément 24h/24, l'application anacron permet de lancer les commandes qui auraient dû l'être lorsque l'ordinateur était éteint.

Utilisation

Lecture de la table

La ligne de commande suivante affiche le contenu de la table cron pour l'utilisateur courant :

$ crontab -l

Cette commande ne permet pas d'afficher la table centralisée (/etc/crontab).

Modification de la table

La commande suivante permet de modifier la table cron pour l'utilisateur courant :

$ crontab -e

Cette commande a pour effet de lancer l'éditeur par défaut<ref>Défini par la variable d'environnement $EDITOR ou $VISUAL</ref> (en général vi). L'éditeur affiche alors la table actuelle. Lors du premier lancement de crontab, la table est vierge, éventuellement composée de commentaires d'aide (lignes commençant par le caractère #).

L'éditeur par défaut se configure à l'aide des variables d'environnement $EDITOR ou $VISUAL. Par exemple, pour configurer l'éditeur vim :

$ export EDITOR=vim

Cette commande ne permet pas non plus de modifier la table centralisée (/etc/crontab).

Remplacement de la table

crontab peut aussi écraser la table courante par une nouvelle. Cette nouvelle table peut être fournie dans un fichier en paramètre :

$ crontab fichier-contenant-la-nouvelle-table.txt
Suppression de la table

La ligne de commande suivante supprime le contenu, sans confirmation, de la table cron pour l'utilisateur courant :

$ crontab -r

Syntaxe de la table

Notation

Chaque entrée de la table (chaque ligne) correspond à une tâche à exécuter et doit respecter cette notation :

mm hh jj MMM JJJ tâche
  • mm représente les minutes (de 0 à 59)
  • hh représente l'heure (de 0 à 23)
  • jj représente le numéro du jour du mois (de 1 à 31)
  • MMM représente l'abréviation du nom du mois (jan, feb, ...) ou bien le numéro du mois (de 1 à 12)
  • JJJ représente l'abréviation du nom du jour ou bien le numéro du jour dans la semaine :
    • 0 = dimanche
    • 1 = lundi
    • 2 = mardi
    • 6 = samedi
    • 7 = dimanche (représenté deux fois pour les deux types de semaine)

Pour chaque valeur numérique (mm, hh, jj, MMM, JJJ) les notations possibles sont :

  • * : à chaque unité (0, 1, 2, 3, 4…)
  • 5,8 : les unités 5 et 8
  • 2-5 : les unités de 2 à 5 (2, 3, 4, 5)
  • */3 : toutes les 3 unités (0, 3, 6, 9…)
  • 10-20/3 : toutes les 3 unités, entre la dixième et la vingtième (10, 13, 16, 19)

Si, sur la même ligne, le « numéro du jour du mois » et le « jour de la semaine » sont renseignés, alors cron exécutera la tâche quand l'un des champs correspond. Par exemple, la ligne suivante indique que la tâche doit être exécutée les vendredis ainsi que le 13 de chaque mois, à minuit :

0 0 13 * 5 tâche
Description de la syntaxe d'une tâche dans un fichier crontab
Journal des opérations

La tâche est une commande à exécuter. Si cette tâche écrit sur sa sortie standard ou son erreur standard, alors le daemon crond les envoie par courriel à l'utilisateur correspondant (celui indiqué par le sixième paramètre).

Afin d'éviter que ces informations soient transmises par courriel, il est possible de les rediriger dans des fichiers. Par exemple :

mm hh jj MMM JJJ tâche  > fichier-1  2> fichier-2  
  • fichier-1 contiendra la sortie standard
  • fichier-2 contiendra l'erreur standard

Ou pour accumuler les sorties et erreur standards dans un même fichier nommé journal.txt :

mm hh jj MMM JJJ tâche >> /mon/répertoire/journal.txt 2>&1
Raccourcis
Raccourcis Description Équivalent
@reboot Au démarrage Aucun
@yearly Tous les ans 0 0 1 1 *
@annually Tous les ans 0 0 1 1 *
@monthly Tous les mois 0 0 1 * *
@weekly Toutes les semaines 0 0 * * 0
@daily Tous les jours 0 0 * * *
@midnight Toutes les nuits 0 0 * * *
@hourly Toutes les heures 0 * * * *
Exemples

Chacun des exemples enregistre l'espace disque libre (commande df) dans le fichier /tmp/df.log à des horaires différents. Afin de conserver l'historique, ces exemples utilisent la redirection >> qui permet d'ajouter les nouvelles données à la fin du fichier (si celui-ci existe déjà, dans le cas contraire il sera créé).

Tous les jours à 23 h 30 :

 30 23 * * * df >> /tmp/df.log

Toutes les heures, passées de 5 minutes :

 5 * * * * df >> /tmp/df.log

Tous les premiers du mois à 23h30 :

 30 23 1 * * df >> /tmp/df.log

Tous les lundis à 22h28 :

 28 22 * * 1 df >> /tmp/df.log

Tous les vendredis et tous les 13 de n'importe quel mois à 11h22 :

 22 11 13 * 5 df >> /tmp/df.log

Tous les vendredis 13 de n'importe quel mois à 11h22 :

 22 11 13 * * [ `date '+\%w'` -eq 5 ] && df >> /tmp/df.log

Du 2 au 5 de chaque mois à 10h12 :

 12 10 2-5 * * df >> /tmp/df.log

Tous les jours pairs du mois à 23h59 :

 59 23 */2 * * df >> /tmp/df.log

Tous les jours ouvrés à 22 heures :

 0 22 * * 1-5 df >> /tmp/df.log

Toutes les 5 minutes :

 */5 * * * * df >> /tmp/df.log

Tous les derniers jours du mois (la barre oblique inversée devant % est obligatoire en édition de crontab, contrairement à l'exécution manuelle de la commande) :

 0 0 28-31 * * [ `/bin/date +\%d` -gt `/bin/date +\%d -d "1 day"` ] && df >> /tmp/df.log


  • Tous les derniers dimanches du mois :
    • Première solution : comparer tous les dimanches avec celui de la semaine d'après.
 0 0 * * 0 [ `/bin/date +\%d` -gt `/bin/date +\%d -d "7 day"` ] && df >> /tmp/df.log
    • Deuxième solution : tester la dernière semaine tous les mois.
 0 0 25-31 1,3,5,7,8,10,12 0 my-script.sh
 0 0 24-30 4,6,9,11 0 my-script.sh
 0 0 22-29 2 0 my-script.sh
    • Troisième solution : lancer un script avec le calendrier.
 0 0 21-31 * * /bin/script.sh
 $ cat /bin/script.sh
$ cat /bin/script.sh
#!/bin/sh

#(Pour les OS où `cal -m` met lundi en position 1)
#dernierdimanche=`cal -m | awk '{print $7}' | tail -1`; #(ERREUR lignes vides si $7="")
#CORRECTIF pour tous les OS
dernierdimanche=`cal -m |awk 'BEGIN{p=7};(NR==2 && $1=="di"){p=1};(NF>=p){di=$p};END{print di};'`;
aujourdhui=`date +%d`

if [ $aujourdhui -eq $dernierdimanche ]
then
df >> /tmp/df.log
else
echo "Nous ne sommes pas encore le dernier dimanche du mois."
fi


    • Quatrième solution, utiliser fcron.
0 0 * * 0 [ `date '+\%e'` -le 7 ] && df >> /tmp/df.log
    • Autre solution : le script avec calendrier :
 0 0 1-7 * * /bin/script2.sh

Modèle:Boîte déroulante début

$ cat /bin/script2.sh
#!/bin/sh

#premierdimanche=`cal -m | awk '{print $7}' | head -3 | tail -1`; #(ERREUR si lundi "")
premierdimanche=`cal -m | awk '(NR==3){print $NF}'`; #(CORRECTIF simple, pour lundi en position 1)
aujourdhui=`date +%d`

if [ $aujourdhui -eq $premierdimanche ]
then
df >> /tmp/df.log
else
echo "Nous ne sommes pas encore le premier dimanche du mois."
fi

Modèle:Boîte déroulante fin

Horodatage du fichier de sortie

Les exemples ci-dessus utilisent la redirection >> afin de créer un journal sur plusieurs exécutions.

Afin, d'écrire dans des fichiers différents, il est possible d'utiliser la commande date, comme avec l'exemple suivant :

 30 23 * * * df > /tmp/df_`date +\%d_\%m_\%Y_\%H_\%M`.log

(le caractère ` (accent grave, U+0060) est produit par la combinaison des touches [Alt Gr]+[7] sur le clavier AZERTY en France)

Bien entendu, une autre solution est de réaliser l'écriture du fichier dans un script appelle-df.sh :

 #!/bin/sh
 JJ_MM_ANNEE_HH_MM=`date +\%d_\%m_\%Y_\%H_\%M`
 df > /tmp/df_${JJ_MM_ANNEE_HH_MM}.log

Et de remplacer la table cron précédente par :

 30 23 * * * appelle-df.sh

Commandes utiles

Ces commandes ne fonctionnent pas pour toutes les distributions Linux et Unix.

Indique l'horaire de la dernière tâche exécutée pour l'ensemble des utilisateurs :

ls -lut /etc/init.d/cron

Extrait du journal du système les informations concernant la table cron :

grep -w cron /var/log/syslog

Relance le démon cron :

/etc/init.d/cron force-reload