Base de connaissances · Linux

Configuration des tâches cron

Dernière mise à jour : 2020-01-18

Veuillez vérifier que vous disposez d'une adresse e-mail valide pour recevoir les messages. Veuillez consulter l'article suivant sur la « configuration des tâches cron » et, si vous avez encore besoin d'aide, ouvrez un ticket de support.

Cron est un aspect souvent confus et mal configuré du système d'exploitation. Techniquement, cron est juste le démon de l'horloge (/usr/sbin/cron ou peut-être /usr/sbin/crond) qui exécute des commandes à des moments précis. Cependant, une poignée de fichiers et de programmes de configuration entrent dans la composition du paquet cron. Comme beaucoup de processus système, cron ne finit jamais.

Les fichiers de contrôle de cron sont les tables de cron ou les crontabs. Les crontabs sont souvent situés dans /var/spool/cron/crontab. Cependant, sur SuSE vous les trouverez dans /var/spool/cron/tabs. Les noms des fichiers de ce répertoire sont les noms des utilisateurs qui soumettent les tâches de cron.

Contrairement à d'autres variantes d'UNIX, le démon cron de Linux ne se met pas en veille jusqu'à la prochaine tâche cron à exécuter. À la place, lorsque cron termine une tâche, il continue de vérifier une fois par minute s'il y a d'autres tâches à lancer. Par ailleurs, vous ne devez pas modifier les fichiers directement. Vous pouvez les modifier avec un éditeur de texte tel que vi, mais vous risquez de provoquer des erreurs. Vous devez donc utiliser l'outil fourni par Linux : crontab. (consultez la page de manuel pour plus de détails)

L'utilitaire crontab remplit plusieurs fonctions. Il permet tout d'abord de soumettre au système les fichiers contenant les tâches cron. Ensuite, il peut afficher le contenu de votre crontab. Si vous êtes root, il peut également soumettre et lister les tâches de n'importe quel utilisateur. Le problème est que les tâches ne peuvent pas être soumises individuellement : avec crontab, vous devez soumettre toutes les tâches en une seule fois.

Cela peut sembler un peu contraignant au premier abord. Examinons toutefois la procédure d'« ajout » d'une tâche. Pour ajouter une tâche cron, vous devez d'abord afficher le contenu de la crontab existante avec l'option -l. Si vous êtes root et souhaitez ajouter une entrée à la crontab d'un autre utilisateur, utilisez l'option -u suivie de l'identifiant de connexion de l'utilisateur. Redirigez ensuite cette crontab vers un fichier, que vous pourrez alors modifier. (Notez que sur certains systèmes, crontab dispose de l'option -e (pour « edit »), qui effectue tout le travail à votre place. Consultez la page de manuel pour plus de détails.)

Par exemple, supposons que vous soyez l'utilisateur root et que vous souhaitiez ajouter une entrée à la crontab de l'utilisateur UUCP. Commencez par récupérer la sortie de l'entrée crontab existante avec cette commande :

crontab -l -u uucp >/tmp/crontab.uucp

Pour ajouter une entrée, ajoutez simplement une nouvelle ligne. Enregistrez le fichier, quittez votre éditeur, puis exécutez à nouveau l'utilitaire crontab. Cette fois, omettez l'option -l qui sert à afficher le fichier, mais indiquez le nom du fichier. L'utilitaire crontab peut également accepter une saisie depuis stdin : vous pouvez donc omettre le nom du fichier et crontab vous permettra de saisir les tâches cron en ligne de commande. N'oubliez pas que toute crontab précédente est supprimée, quelle que soit la méthode utilisée.

Le fichier /tmp/crontab.uucp contient maintenant le contenu de UUCPs crontab. Ça pourrait ressembler à ça.

39,9 * * * * /usr/lib/uucp/uudemon.hour > /dev/null
10 * * * * /usr/lib/uucp/uudemon.poll > /dev/null
45 23 * * * ulimit 5000; /usr/lib/uucp/uudemon.clean > /dev/null
48 10,14 * * 1-5 /usr/lib/uucp/uudemon.admin > /dev/null

Malgré les apparences, chaque entrée de crontab ne comporte que six champs. Les cinq premiers indiquent l'heure d'exécution de la tâche et le sixième correspond à la commande proprement dite. Les cinq premiers champs sont séparés par un espace ou une tabulation et représentent respectivement les unités suivantes :

minutes (0-59)
heure (0-23)
jour du mois (1-31)
mois de l'année (1-12)
jour de la semaine (0-6, 0=dimanche)
Pour spécifier toutes les valeurs possibles, utilisez un astérisque (*). Vous pouvez indiquer une valeur unique en saisissant simplement cette valeur. Par exemple, la deuxième ligne de l'exemple précédent a la valeur 10 dans le premier champ, ce qui signifie 10 minutes après l'heure pile. Comme les quatre autres champs de temps contiennent des astérisques, la commande est exécutée toutes les heures, tous les jours, à 10 minutes après l'heure pile.

Les plages de valeurs sont composées de la première valeur, d'un tiret et de la dernière valeur. Par exemple, la quatrième ligne comporte une plage (1-5) dans la colonne du jour de la semaine, ce qui signifie que la commande n'est exécutée que du jour 1 au jour 5, c'est-à-dire du lundi au vendredi.

Pour spécifier différentes valeurs qui ne sont pas dans une plage, séparer les valeurs individuelles par une virgule. Dans le quatrième exemple, le champ heure a les deux valeurs 10 et 14. Cela signifie que le commandement est exécuté à 10 h et 14 h.

Notez que les conditions de temps s'additionnent. Examinons un exemple :


10 * 1,16 * 1-5 /usr/local/bin/command


La commande est exécutée 10 minutes après chaque heure, le premier et le seizième jour du mois, ainsi que du lundi au vendredi. Si le premier ou le seizième tombe un week-end, la commande sera tout de même exécutée, car le champ du jour du mois s'applique. Cela ne signifie pas pour autant que si le premier est un lundi, la commande est exécutée deux fois.

L'entrée crontab peut être définie pour s'exécuter à d'autres intervalles que toutes les heures ou tous les jours. La granularité peut être réglée à toutes les deux minutes ou toutes les trois heures, sans avoir à saisir chaque entrée individuellement dans la crontab.

Supposons que nous souhaitions exécuter la commande précédente non pas à 10 minutes après l'heure pile, mais toutes les dix minutes. Nous pourrions créer une entrée de ce type :


0,10,20,30,40,50 * 1,16 * 1-5 /usr/local/bin/command


Elle s'exécute toutes les 10 minutes : à l'heure pile, 10 minutes après, 20 minutes après, et ainsi de suite. Pour simplifier, nous pourrions créer l'entrée de la façon suivante :


*/10 * 1,16 * 1-5 /usr/local/bin/command


Cette syntaxe peut être nouvelle pour certains administrateurs. (Elle l'était pour moi.) La barre oblique (/) indique que, dans l'intervalle spécifié (ici, chaque minute), la commande doit être exécutée toutes les x minutes ; dans ce cas, toutes les 10 minutes.

Nous pouvons également l'utiliser lorsque nous spécifions une plage. Par exemple, si la tâche ne devait s'exécuter qu'entre 20 minutes et 40 minutes après l'heure pile, l'entrée pourrait ressembler à ceci :


20-40 * 1,16 * 1-5 /usr/local/bin/command


Et si vous souhaitiez qu'elle s'exécute pendant ces mêmes plages, mais seulement toutes les trois minutes ? La ligne pourrait ressembler à ceci :


20-40/3 * 1,16 * 1-5 /usr/local/bin/command


Pour compliquer encore davantage les choses, vous pourriez demander que la commande s'exécute toutes les deux minutes entre l'heure pile et 20 minutes après, toutes les trois minutes entre 20 et 40 minutes après, puis toutes les 5 minutes entre 40 minutes après et l'heure pile.


0-20/2,21-40/3,41-59/5 * 1,16 * 1-5 /usr/local/bin/command


Une très bonne chose que permettent de nombreuses variantes de Linux est de pouvoir indiquer des abréviations pour les jours de la semaine et les mois. Il est beaucoup plus facile de retenir que fri correspond à vendredi (Friday) plutôt que 5.

À l'exception de certaines erreurs dans les champs de date et d'heure, les erreurs ne sont signalées que lorsque cron exécute la commande. Tous les messages d'erreur et toutes les sorties sont envoyés par courrier électronique aux utilisateurs. C'est du moins ce qu'indique la page de manuel de crontab, et c'est globalement exact. Toutefois, comme vous l'avez vu dans les exemples précédents, vous redirigez stdout vers /dev/null. Si vous le souhaitiez, vous pourriez aussi y rediriger stderr, et vous ne sauriez alors jamais si des erreurs se sont produites.

La sortie est envoyée par courrier électronique à l'utilisateur, car les tâches cron ne sont pas exécutées dans un véritable terminal. Il n'y a donc pas d'écran pour afficher les erreurs, ni de clavier pour saisir des données. Cela signifie-t-il qu'il est impossible de fournir une entrée à une tâche cron ? Non. Rappelez-vous ce que nous avons vu à propos des scripts shell : nous pouvons redéfinir stdin, stdout et stderr. Ils peuvent ainsi tous pointer vers des fichiers et se comporter comme nous le souhaitons.

Je tiens à souligner que je ne recommande pas de faire de la redirection dans le champ de commande de la crontab. Je préfère y en faire le moins possible. À la place, j'indique le chemin absolu d'un script shell. Je peux ainsi tester l'entrée de la crontab avec quelque chose de simple. Une fois que cela fonctionne, je peux modifier le script shell sans avoir à soumettre de nouveau la tâche cron.

Gardez à l'esprit que cron n'est pas exact. Il se synchronise au début de chaque minute. Sur un système très chargé où des tics d'horloge sont perdus, il est possible que les tâches ne soient exécutées que quelques minutes après l'heure prévue. De plus, d'autres processus de priorité supérieure peuvent retarder les tâches cron. Dans certains cas (en particulier sur des systèmes très chargés), des tâches exécutées chaque minute peuvent finir par être ignorées.

L'accès au service cron est géré par deux fichiers, tous deux situés dans /etc. Si vous disposez d'un fichier cron.allow, vous pouvez y indiquer les utilisateurs autorisés à utiliser cron. Le fichier cron.deny indique quant à lui les utilisateurs qui n'y sont explicitement pas autorisés. Si aucun de ces fichiers n'existe, seuls les utilisateurs du système y ont accès. Toutefois, si vous souhaitez que tout le monde y ait accès, créez un fichier cron.deny vide. Autrement dit, aucun utilisateur n'est exclu.

Il est souvent utile pour root d'exécuter des tâches en tant qu'utilisateur différent sans avoir à changer d'utilisateur (par exemple, en utilisant la commande su). La plupart des dialectes Linux fournissent un mécanisme sous la forme du fichier /etc/crontab. Ce fichier n'est généralement enregistrable que par racine et dans certains cas, seule racine peut le lire (ce qui est souvent nécessaire dans des environnements de haute sécurité). La syntaxe générale est la même que les crontabs standards, à quelques exceptions près.

La première différence concerne l'en-tête, que vous pouvez voir ici :


SHELL=/bin/sh
PATH=/usr/bin:/usr/sbin:/sbin:/bin:/usr/lib/news/bin
MAILTO=root
#
# check scripts in cron.hourly, cron.daily, cron.weekly, and cron.monthly
#

59 * * * * root rm -f /var/spool/cron/lastrun/cron.hourly
14 0 * * * root rm -f /var/spool/cron/lastrun/cron.daily
29 0 * * 6 root rm -f /var/spool/cron/lastrun/cron.weekly
44 0 1 * * root rm -f /var/spool/cron/lastrun/cron.monthly

La variable SHELL définit le shell sous lequel chaque commande sera exécutée. La variable PATH est semblable à la variable d'environnement PATH habituelle et définit le chemin de recherche. La variable MAILTO indique qui doit recevoir les courriers électroniques, y compris les messages d'erreur et la sortie standard des commandes exécutées.

La structure des entrées réelles est à peu près la même, à l'exception du nom d'utilisateur (root dans chaque cas ici). De cette façon, les utilisateurs root (ou qui peut éditer /etc/crontab) peuvent définir quel utilisateur exécute la commande. Gardez à l'esprit que cela peut être un gros trou de sécurité. Si quelqu'un peut écrire dans ce fichier, il peut créer une entrée qui fonctionne comme racine et a donc le contrôle complet du système.

La commande suivante de la « suite » cron est at. Sa fonction est d'exécuter une commande à un moment précis. La différence est qu'une fois la tâche at exécutée, elle disparaît du système. Comme pour cron, deux fichiers, at.allow et at.deny, ont le même effet sur le programme at.

La commande batch sert également à exécuter des commandes une seule fois. Toutefois, les commandes soumises avec batch sont exécutées lorsque le système en a le temps, c'est-à-dire lorsqu'il est moins sollicité, par exemple au milieu de la nuit. Il est possible que ces tâches soient réparties sur toute la journée, selon la charge du système.

Il faut noter le comportement de at et de batch. Tous deux acceptent les noms des commandes depuis la ligne de commande et non comme arguments de la commande elle-même. Vous devez d'abord lancer la commande pour passer à une nouvelle ligne, où vous saisissez les commandes à exécuter. Après chaque commande, appuyez sur Entrée. Lorsque vous avez terminé, appuyez sur Ctrl-D.

Comme ces deux commandes acceptent des commandes depuis stdin, vous pouvez les saisir sans avoir à passer à une nouvelle ligne à chaque fois. Une possibilité consiste à rediriger l'entrée depuis un fichier. Par exemple :


at now +1 hour < command_list


où command_list est un fichier contenant une liste de commandes. Vous pouvez aussi placer at (ou batch) à la fin d'un tube :


cat command_list | at now + 1 hour

cat command_list | batch

Une autre chose intéressante à propos de la fois à et batch est qu'ils créent une sorte de script shell pour exécuter votre commande. Lorsque vous lancez à ou par lots, un fichier est créé dans /usr/spool/cron/atubs. Ce fichier contient les variables système que vous auriez normalement définies, ainsi que d'autres informations contenues dans /usr/lib/cron.proto. Cela crée essentiellement un environnement comme si vous vous étiez connecté.

← Tous les articles de la base de connaissances

Tell us what you need

Compare available plans or describe your workload so we can discuss a suitable starting point.