CRON et la planification de tâches
Le 8 novembre 2008 à 20:06.

Difficile de se passer d'un planificateur de tâche, que ce soit pour faire des sauvegardes, vérifier l'intégrité des systèmes, faire le ménage ou bêtement se réveiller le matin. Sous UNIX, le temps c'est le domaine du vénérable CRON.

Principe

CRON est un démon de l'ancien monde, à peu prés aussi vieux qu' UNIX lui-même. Et pour les connaisseurs, sachez qu'il n'a rien à voir avec la divinité cimmérienne, en toute banalité son nom vient du grec "chronos" (χρόνος), le temps.

CRON est un planificateur de tâches dont le rôle est simplement d'exécuter des commandes récurrentes, chacune sur une base de temps donnée (toutes les heures, à une heure particulière chaque jour, au début de chaque mois, etc...).

La version simplifiée

Comme nous allons le voir plus loin, ajouter une tâche dans CRON nécessite de connaître sa syntaxe et de modifier le bon fichier de planning. Cependant sur certaines distribution comme la Mandriva, CRON est pré-configuré de telle sorte que les commandes (ou plus généralement des liens symboliques vers des commandes) contenues dans les dossiers /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly et /etc/cron.monthly, soient exécutées respectivement tous les jours, toutes les heures, toutes les semaines et tous les mois.

Du coup si vous avez seulement besoin de récurrence de ce type (heure, jour, semaine et mois), pas la peine de sortir la grosse artillerie, un simple lien symbolique suffit à planifier la tâche :

# lancer la tâche backup tous les jours
root#ln -s /usr/bin/backup /etc/cron.daily
 
# vérifier le système toutes les heures
root#ln -s /usr/bin/check_system /etc/cron.hourly
root# 

Syntaxe des plannings

Bien que pratique, le système par liens symbolique ne répond pas à tous les besoins. Et pour programmer une tâche aussi spécifique que "tous dimanches à l'heure de la messe", il faut mettre un peu plus les mains dans le cambouis.

Les plannings de tâches sont constitués par de simple fichier texte utilisant une syntaxe particulière. Le planning principal est /etc/crontab que très logiquement seul l'utilisateur root peut modifier. Mais pour éviter que ce fichier ne deviennent trop gros et aussi gagner en modularité, il est préférable de créer des micros-plannings dans le dossier /etc/cron.d. La syntaxe sera rigoureusement la même.

Un fichier planning peut commencer par une section de définition de variable. Nous allons grâce à ces variables pouvoir définir dans le contexte d'un même planning : le chemin des exécutable (PATH), le shell à utiliser par défaut (SHELL), le dossier de démarrage (HOME) et l'adresse courriel à utiliser pour envoyer à un tiers le résultat de la commande (MAILTO).

Ces variables sont importante car vous ne savez par exemple jamais quelle est la valeur de la variable PATH au sein d'un CRON, ni quel sera le dossier de démarrage. Elles permettent donc de fixer le contexte de manière fiable.

Dans une autre idée MAILTO définit quant à elle à qui sera expédié le mail qui contient tout ce qui a été "écrit" par une commande (messages, erreurs, etc). Notre premier planning va donc pouvoir ressembler à cela :

#! /bin/sh

# définition des variables spécifiques au planning
# ###################################################
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=mon_mail  @mon_domain.com
HOME=/root

# Une tâche du planning
*/1 * * * * root ls -la    
/etc/cron.d/mon_planing

Si votre système est correctement configuré, vous devriez dans la minute qui suit (les plannings sont automatiquement pris en compte) recevoir par mail à l'adresse le contenu du dossier /root (cf la variable HOME). Et ce, toutes les minutes... Lorsque vous aurez constaté que cela fonctionne, vous pouvez éditer à nouveau ce planning pour mettre la ligne qui lance la commande ls en commentaire en ajoutant un # en tête.

Comme vous le voyez le fichier planning contient une ligne par tâche planifiée. Chaque ligne est d'abord composée de 5 champs permettant de déterminer le moment du lancement. Suit ensuite l'identifiant l'utilisateur qui sera utilisé pour lancer cette commande, puis la commande elle-même comprenant tout ce qui se trouve après l'identifiant de l'utilisateur. Chaque champs est séparé par des espaces ou des tabulations.

Les 5 champs qui définissent le moment du lancement sont :

minutes
Une valeur numérique allant de 0 à 59.
heure
Une valeur numérique allant de 0 à 23.
jour du mois
Une valeur numérique allant de 1 à 31.
mois
Une valeur numérique allant de 1 à 12.
jour de la semaine
Une valeur numérique de 1 à 7.

Pour les deux derniers champs, la dernière valeur (12 et 7) et 0 sont généralement synonymes mais il est plus simple de ne pas trop y compter. Enfin ces valeurs peuvent aussi être les 3 premières lettres du mois ou du jour de la semaine. Mais là aussi, d'un UNIX à l'autre, c'est de l'anglais ou du français. De plus certains ne prennent pas en charge cette notation pour les listes et les intervalles (voir plus loin).

Chaque champ peut prendre une valeur précise, ou un intervalle de valeur. L'intervalle le plus simple est * signifiant "tout". Ainsi pour lancer une tâche tous les mois, toutes les semaines, tous les jours et à la 2ième minute de chaque heure, cela donne :

02 * * * * gaston /usr/bin/ma_command
/etc/cron.d/exemples

Il est aussi possible de spécifier une liste de valeur en séparant chacune par une virgule. Par exemple pour lancer la même commande que plus haut mais à la 2ième et 42ième minute :

02,42 * * * *  gaston /usr/bin/ma_command
/etc/cron.d/exemples

L'étoile spécifie un intervalle complet, mais nous pouvons aussi utiliser un intervalle restreint. Par exemple une commande lancée la 2ième minute de chaque heure mais de cette fois de 10h du matin à 6h du soir, cela donnerait :

02 10-18 * * *  gaston /usr/bin/ma_command
/etc/cron.d/exemples

Et comme pour les valeurs simples, vous pouvez définir des listes d'intervalles. Par exemple si l'on veut exclure l'heure du déjeuné, cela nous fait deux intervalles :

02 10-12,14-18 * * * gaston /usr/bin/ma_command
/etc/cron.d/exemples

Dernier point, il est possible de dire des choses du genre "toutes les deux heures" en ajoutant un pas à l'intervalle sous la forme intervalle/pas. Pour par exemple effectuer une tâche toutes les 15 minutes, nous affecterons le pas "15" à l'intervalle complet *, soit :

*/15 * * * * gaston /usr/bin/ma_command
/etc/cron.d/exemples

Cette notation de "pas" ne change en rien les propriétés de l'intervalle. Il est donc possible, de faire des listes d'intervalles avec pas. Par exemple toutes des 2 h, de 8h à 12h et de 14h à 18h, à la 2ième minute se note :

2 8-12/2,14-18/2 * * * gaston /usr/bin/ma_command
/etc/cron.d/exemples

Une fois que l'on a mémorisé les différents motifs (valeur, intervalle, liste et pas), l'ajout de nouvelles tâche est très simple. Par exemple pour envoyer un mail tous les jours ouvré à 1h du matin cela nous donne :

0 1 * * 1-5 trichelieu echo "Il est une heure,% tout va bien !!" | mail -s "Rapport" compagnie@son_domaine.net
/etc/cron.d/tour_de_garde

A noter que le caractère % dans la commande est automatiquement changé en "retour chariot". Pour un vrai %, il faut taper \%.

CRON utilisateur

/etc/crontab ou /etc/cron.d ne sont accessible qu'à root. Il est cependant offert à chaque utilisateur la possibilité de disposer de sa propre planification de tâche qui sera alors stockée en /var/spool/cron/nom_utilisateur.

Ne pouvant pas éditer cela directement, il doit utiliser la commande crontab

crontab -l
Vérifier si une table existe déjà et la lister si c'est le cas.
crontab -e
Éditer la table avec vi. Si cet éditeur ne vous plaît pas, ce qui serait surprenant, faite un export EDITOR=gedit avant.
crontab nom_fichier
Pour importer une table existante.
crontab -r
Suppression de la table utilisateur.

A noter que certains utilisateurs peuvent être interdits, ou explicitement autorisés à utiliser leur crontab en modifiant les fichier /etc/cron.allow et /etc/cron.deny.

Conclusion

CRON fait parti de ces concepts UNIX indispensables à maîtriser et que pourtant beaucoup considèrent, à tord, comme complexe. J'espère que ce n'est maintenant plus le cas.

Commentaires

rodhia, le 8 November, 2008 - 22:08

Sympa les précisions! Tu sais si il est possible de lancer une tâche au log in d'un utilisateur?

nico_ze_poo , le 8 November, 2008 - 22:19

Cron ne fait que de la planification.
PAM serait plus adapté, et Ulhume nous a pondu un magnifique article à son sujet Big grin

Ulhume, le 8 November, 2008 - 22:24

Ban, j'ai plus rien à dire quoi Smiling

En effet, le plus simple pour lancer une action au login de l'utilisateur, ou au logout c'est d'utiliser pam_script.

rodhia, le 8 November, 2008 - 22:28

Glad je vais étudier tout ça ! merci

sbk , le 8 November, 2008 - 22:44

Également utile pour les stations de travail qui ne sont pas allumés en permanence : Anacron.
Contrairement à Cron, il va executer la tâche recurrente même si le temps est dépassé (par exemple au prochain demarage de la machine si celle ci est éteinte).

Ulhume, le 8 November, 2008 - 23:25

@sbk yep, j'ai vu apparaître ce bidule avec la driva 2009, en revanche j'ai pas encore cherché où était sa table de planification.

tuxce , le 9 November, 2008 - 01:35

au même endroit que celle de cron:/etc/anacrontab

ce qui peut être interessant avec vixie cron (ne fonctionne pas avec toutes les déclinaisons), c'est la directive @reboot par exemple qui permet de relancer un programme au boot même en utilisateur et sans avoir à se loguer. Ca peut etre utiliser par exemple pour un "fetchmail"... (par contre, ca peut etre une faille aussi Wink)

Dab, le 9 November, 2008 - 16:34

Je suis à la recherche d'un équivalent de Control-M ( http://en.wikipedia.org/w/index.php?title=CONTROL-M ) sous Linux, en opensource bien sur. En gros un ordonnanceur de tache, un peu comme cron mais beaucoup plus souple. Genre exécute le script machin.sh sur la machine A à telle heure si le script toto de la machine B s'est bien exécuté et que titi.sh s'est mal terminé et que nous sommes le premier dimanche du mois ou que ... le tout programmé de manière graphique. Super produit BMC http://media.bmc.com/edu/CONTROL_M_2ME/CONTROL_M_preso.html , super cher Frown Quelqu'un aurait une idée ?

Ulhume, le 9 November, 2008 - 17:08

@dab ma langue au chat, peut-être que freeflyer a une idée là dessus, c'est lui aussi son métier Smiling

bulldorack, le 9 November, 2008 - 23:29

Je doute que ce soit aussi puissant que Control-M, mais en open source, il y a les 2 softs suivants:

  • Job Scheduler
  • JOb Scheduling Hierarchically (JOSH)

    Pas testé personnellement, donc je ne sais pas ce que ça vaut...

  • Dab, le 10 November, 2008 - 02:14

    Merci, très intéressants ces liens

    Emmanel , le 10 November, 2008 - 05:12

    On peut également signaler la commande At pour la planification non répétitive. Je m'en sers, par exemple, pour m'envoyer des mémos par mail :

    toto~> echo "echo \"Ne pas oublier\" | mail monadresse -s \"RDV dentiste à 15h00\""|at 09:00 11/12/2008

    Ulhume, le 10 November, 2008 - 11:03

    @emmanuel tu es un vrai unixien toi Smiling

    Sinon en effet AT peut être assez pratique au cas par cas. A noter à ce moment là aussi pour quoi ne l'utilise jamais qu'il est lié à un démon (atd) qui est possible d'arrêter si la mémoire est un peu courte.

    Anonymous , le 13 November, 2008 - 14:15

    00 18 * * * amportal restart /bin/sh

    Comment savoir que ça s'est bien exécuté par mail ou autre chose

    Ulhume, le 13 November, 2008 - 14:27

    @Anonymous (je pense que je vais interdire ce psoeudo à un moment ou à une autre Wink

    CRON envoie par mail le résultat de la commande (stderr ou stdout). Donc si la commande ne dis "rien", il n'y a aucun moyen de savoir si elle est passée.

    gazza (remplace anonymous) , le 13 November, 2008 - 14:57

    comment donc faire en sorte que je puisse le transférer par mail le résultat de ma crontab merci

    Ulhume, le 13 November, 2008 - 16:26

    @gazza simplement, comme indiqué dans le billet, en renseignant la variable MAILTO (voir plus haut).

    gazza (remplace anonymous) , le 13 November, 2008 - 18:39

    J'ai renseignéla variable

    Mailto= // concrètement comment faire pour le recevoir via mon mail document.write(String.fromCharCode(60,97,32,104,114,101,102,61,39,109,97,105,108,116,111,58,105,101,108,108,97,103,97,122,122,97,64,121,97,104,111,111,46,102,114,39,62,105,101,108,108,97,103,97,122,122,97,64,121,97,104,111,111,46,102,114,60,47,97,62));">

    Mais j'ai pas de news sur le déroulement de la commande effectuée par crontab!
    Cependant, en allant voir du coté de cat /var/log/cron j'ai l'impression que ça s'éxecute

    Ulhume, le 13 November, 2008 - 18:48

    @gazza pour la recevoir il faut que la machine qui exécute cron ait un serveur sendmail/smtp.

    Une version light pour relayer vers un serveur SMTP réel :
    http://artisan.karma-lab.net/node/1171

    Similitux , le 27 January, 2009 - 13:46

    Ha Reflets d'Acide ! Que du bonheur !

    Ulhume, le 27 January, 2009 - 14:22

    héhé, je me demandais si quelqu'un trouverait la référence Wink

    Poster un nouveau commentaire

    Si vous avez détecté une erreur, coquille ou bêtises du même ordre, merci de plutôt passer par le formulaire de contact
    Pour vous abonner au flux des commentaires sur cet article, clickez ici.
    Pour répondre à quelqu'un, utilisez plutôt le lien répondre qui se trouve en haut (ou en bas) à gauche de son commentaire.
    Le contenu de ce champ est gardé secret et ne sera pas montré publiquement. If you have a Gravatar account, used to display your avatar.
    • To highlight piece of code, just surround them with <code type="language"> Your code &tl;/code>>. Language can be java,c++,bash,etc... Everything Geshi support.
    • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <blockquote> <div>
    • Les lignes et les paragraphes vont à la ligne automatiquement.
    • Textual smileys will be replaced with graphical ones.
    • Les adresses de pages web et de messagerie électronique sont transformées en liens automatiquement.

    Plus d'informations sur les options de formatage


    Connexion utilisateur
    Les derniers bavardages...