401 votes

Pourquoi mon crontab ne fonctionne-t-il pas et comment puis-je le résoudre ?

Il s'agit d'un Question canonique sur l'utilisation de cron et crontab.

Vous avez été dirigé ici parce que la communauté est assez sûre que la réponse à votre question peut être trouvée ci-dessous. Si votre question ne trouve pas de réponse ci-dessous, les réponses vous aideront à rassembler des informations qui permettront à la communauté de vous aider. Ces informations doivent être éditées dans votre question originale.

La réponse à la question Pourquoi mon crontab ne fonctionne-t-il pas et comment puis-je le résoudre ? peut être vu ci-dessous. Cela répond à la cron système avec la crontab en surbrillance.

4 votes

C'est une énorme copie de Raisons pour lesquelles la crontab ne fonctionne pas sur AskUbuntu.

1 votes

Il semble qu'Eric ait besoin d'avoir plus de réputation.

1 votes

Je viens de rejoindre Server Fault SE (donc seulement 101 rep), mais j'aimerais donner un -1 à cette question ! Cette question a-t-elle été posée uniquement pour obtenir des points de fidélité ? @IamtheMostStupidPerson Totalement d'accord avec vous...

551voto

Eric Leschinski Points 3812

Comment résoudre tous vos problèmes de crontab (Linux)


Il s'agit d'un wiki communautaire Si vous remarquez une erreur dans cette réponse ou si vous avez des informations supplémentaires, veuillez la modifier.


Tout d'abord, la terminologie de base :

  • cron(8) est le démon qui exécute les commandes programmées.
  • crontab(1) est le programme utilisé pour modifier les fichiers crontab(5) des utilisateurs.
  • crontab(5) est un fichier par utilisateur qui contient les instructions pour cron(8).

Ensuite, éducation sur le cron :

Chaque utilisateur d'un système peut avoir son propre fichier crontab. L'emplacement des fichiers crontab de la racine et de l'utilisateur dépend du système, mais ils sont généralement situés aux endroits suivants /var/spool/cron .

Il existe un système /etc/crontab le fichier /etc/cron.d peut contenir des fragments de crontab qui sont également lus et traités par cron. Certaines distributions de Linux (par exemple, Red Hat) disposent également de /etc/cron.{hourly,daily,weekly,monthly} qui sont des répertoires, scripts à l'intérieur desquels seront exécutés toutes les heures/jours/semaines/mois, avec le privilège de root.

Le super-utilisateur peut toujours utiliser la commande crontab ; les utilisateurs ordinaires peuvent ou non obtenir un accès. Lorsque vous modifiez le fichier crontab avec la commande crontab -e et le sauvegarder, crond vérifie sa validité de base mais ne garantit pas que votre fichier crontab soit correctement formé. Il existe un fichier appelé cron.deny qui spécifiera quels utilisateurs ne peuvent pas utiliser cron. L'adresse cron.deny L'emplacement du fichier dépend du système et peut être supprimé, ce qui permettra à tous les utilisateurs d'utiliser cron.

Si l'ordinateur n'est pas sous tension ou que le démon crond n'est pas en cours d'exécution, et que la date/heure d'exécution d'une commande est passée, crond ne rattrapera pas et n'exécutera pas les requêtes passées.

Les particularités de la crontab, comment formuler une commande :

Une commande crontab est représentée par une seule ligne. Vous ne pouvez pas utiliser \ pour étendre une commande sur plusieurs lignes. Le dièse ( # ) représente un commentaire, ce qui signifie que tout ce qui se trouve sur cette ligne est ignoré par cron. Les espaces et les lignes vides sont ignorés.

Soyez TRÈS prudent lorsque vous utilisez le pourcentage ( % ) dans votre commande. À moins qu'ils ne soient échappés \% ils sont convertis en nouvelles lignes et tout ce qui se trouve après le premier élément non échappé est converti en lignes. % est transmis à votre commande sur stdin.

Il existe deux formats pour les fichiers crontab :

  • Utilisateur crontabs

     # 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)
     # |  |  |  |  |
     # *  *  *  *  *   command to be executed
  • Dans tout le système /etc/crontab y /etc/cron.d fragments

     # 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)
     # |  |  |  |  |
     # *  *  *  *  * user-name  command to be executed

Notez que ce dernier requiert un nom d'utilisateur. La commande sera exécutée en tant que l'utilisateur nommé.

Les 5 premiers champs de la ligne représentent le(s) moment(s) où la commande doit être exécutée. Vous pouvez utiliser des chiffres ou, le cas échéant, des noms de jour/mois dans la spécification de l'heure.

  • Les champs sont séparés par des espaces ou des tabulations.
  • Une virgule ( , ) est utilisé pour spécifier une liste, par exemple 1,4,6,8 qui signifie exécuter à 1,4,6,8.
  • Les intervalles sont spécifiés avec un tiret ( - ) et peuvent être combinés avec des listes, par exemple 1-3,9-12 qui signifie entre 1 et 3 puis entre 9 et 12.
  • El / peuvent être utilisés pour introduire une étape, par exemple 2/5, qui signifie que l'on commence à 2 puis tous les 5 (2,7,12,17,22...). Ils ne s'enroulent pas au-delà de la fin.
  • Un astérisque ( * ) dans un champ signifie l'ensemble de la plage pour ce champ (ex. 0-59 pour le champ des minutes).
  • Les gammes et les étapes peuvent être combinées, par exemple. */2 signifie qu'il faut commencer par le minimum pour le champ concerné puis tous les 2, par exemple 0 pour les minutes( 0,2...58), 1 pour les mois (1,3 ... 11) etc.

Débogage des commandes cron

Vérifiez le courrier !

Par défaut, cron enverra toute sortie de la commande à l'utilisateur sous lequel il exécute la commande. S'il n'y a pas de sortie, il n'y aura pas de courrier. Si vous voulez que cron envoie le courrier à un autre compte, vous pouvez définir la variable d'environnement MAILTO dans le fichier crontab, par ex.

MAILTO=user@somehost.tld
1 2 * * * /path/to/your/command

Capturez vous-même le résultat

Vous pouvez rediriger stdout et stderr vers un fichier. La syntaxe exacte pour capturer la sortie peut varier en fonction de ce que Shell cron utilise. Voici deux exemples qui enregistrent toute la sortie dans un fichier à l'adresse /tmp/mycommand.log :

1 2 * * * /path/to/your/command &>/tmp/mycommand.log
1 2 * * * /path/to/your/command >/tmp/mycommand.log 2>&1

Regardez les journaux

Cron enregistre ses actions via syslog, qui (en fonction de votre configuration) va souvent à /var/log/cron o /var/log/syslog .

Si nécessaire, vous pouvez filtrer les instructions cron avec, par exemple, les éléments suivants

grep CRON /var/log/syslog 

Maintenant que nous avons passé en revue les bases de cron, où se trouvent les fichiers et comment les utiliser, examinons quelques problèmes courants.

Vérifiez que cron est en cours d'exécution

Si cron ne fonctionne pas, vos commandes ne seront pas planifiées...

ps -ef | grep cron | grep -v grep

devrait vous donner quelque chose comme

root    1224   1  0 Nov16 ?    00:00:03 cron

または

root    2018   1  0 Nov14 ?    00:00:06 crond

Sinon, redémarrez-le

/sbin/service cron start

または

/sbin/service crond start

Il existe peut-être d'autres méthodes ; utilisez ce que votre distro fournit.

cron exécute votre commande dans un environnement restreint.

Les variables d'environnement disponibles sont probablement très limitées. Typiquement, vous n'aurez que quelques variables définies, telles que $LOGNAME , $HOME y $PATH .

Il convient de noter que PATH est limité à /bin:/usr/bin . La grande majorité des problèmes "mon cron script ne fonctionne pas" sont causés par ce chemin restrictif. . Si votre commande se trouve à un autre endroit, vous pouvez résoudre ce problème de plusieurs façons :

  1. Indiquez le chemin complet de votre commande.

     1 2 * * * /path/to/your/command
  2. Fournir un PATH approprié dans le fichier crontab

     PATH=/bin:/usr/bin:/path/to/something/else
     1 2 * * * command 

Si votre commande nécessite d'autres variables d'environnement, vous pouvez également les définir dans le fichier crontab.

cron exécute votre commande avec cwd == $HOME

Indépendamment de l'endroit où le programme que vous exécutez réside sur le système de fichiers, le répertoire de travail actuel du programme lorsque cron l'exécute sera le répertoire personnel de l'utilisateur . Si vous accédez à des fichiers dans votre programme, vous devrez en tenir compte si vous utilisez des chemins relatifs, ou (de préférence) utiliser des chemins entièrement qualifiés partout, et épargner à tout le monde beaucoup de confusion.

La dernière commande dans ma crontab ne s'exécute pas

Cron exige généralement que les commandes soient terminées par une nouvelle ligne. Editez votre crontab ; allez à la fin de la ligne qui contient la dernière commande et insérez une nouvelle ligne (appuyez sur entrée).

Vérifiez le format de la crontab

Vous ne pouvez pas utiliser un crontab formaté utilisateur pour /etc/crontab ou les fragments dans /etc/cron.d et vice versa. Une crontab formatée utilisateur n'inclut pas le nom d'utilisateur en 6ème position d'une ligne, alors qu'une crontab formatée système inclut le nom d'utilisateur et exécute la commande en tant que cet utilisateur.

J'ai mis un fichier dans /etc/cron.{hourly,daily,weekly,monthly} et il ne fonctionne pas.

  • Vérifiez que le nom du fichier n'a pas d'extension voir pièces de rechange
  • Assurez-vous que le fichier a les droits d'exécution.
  • Indiquer au système ce qu'il doit utiliser lors de l'exécution de votre script (ex. mettre #!/bin/sh en haut)

Bogues liés à la date Cron

Si votre date a été récemment modifiée par un utilisateur ou une mise à jour du système, un fuseau horaire ou autre, alors crontab commencera à se comporter de manière erratique et à présenter des bogues bizarres, parfois fonctionnant, parfois non. C'est la tentative de crontab d'essayer de "faire ce que vous voulez" lorsque l'heure change sous ses pieds. Le champ "minute" deviendra inefficace après le changement d'heure. Dans ce scénario, seuls les astérisques seraient acceptés. Redémarrez cron et réessayez sans vous connecter à l'Internet (pour que la date n'ait pas la possibilité de se réinitialiser sur l'un des serveurs de temps).

Des signes de pourcentage, encore

Pour souligner l'importance des pourcentages, voici un exemple de ce que fait cron avec eux :

# cron entry
* * * * * cat >$HOME/cron.out%foo%bar%baz

créera le fichier ~/cron.out contenant les 3 lignes suivantes

foo
bar
baz

Cela est particulièrement gênant lorsque l'on utilise le date commande. Assurez-vous d'échapper aux signes de pourcentage

* * * * * /path/to/command --day "$(date "+\%Y\%m\%d")"

Méfiez-vous du Sudo

lorsqu'il est exécuté en tant qu'utilisateur non root,

crontab -e

ouvrira la crontab de l'utilisateur, alors que

sudo crontab -e

ouvrira la crontab de l'utilisateur root. Il n'est pas recommandé d'exécuter des commandes sudo dans une tâche cron, donc si vous essayez d'exécuter une commande sudo dans le cron d'un utilisateur, essayez de déplacer cette commande dans le cron de root et supprimez sudo de la commande.

0 votes

Vous pouvez également mentionner dans la section 'restricted env' que LD_LIBRARY_PATH peut également avoir besoin de répertoires supplémentaires au cas où votre tâche cron échoue parce qu'elle ne trouve pas les bibliothèques partagées.

0 votes

Notez que vous pouvez même écrire quelque chose comme ça : 35 1,5-23/2 * * * faire_quelque chose au lieu de 35,1,5,7,9, * * * En plus de cela crontab.guru traduit les entrées que vous faites en langage humain.

1 votes

La capture de sortie ne fonctionne pas pour moi, peut-être à cause du sh Shell. Je pense que c'est plus portable : ... /path/to/your/command >/tmp/mycommand.log 2>&1

39voto

wazoox Points 6554

Debian Linux et ses dérivés (Ubuntu, Mint, etc.) ont quelques particularités qui peuvent empêcher vos tâches cron de s'exécuter ; en particulier, les fichiers dans le répertoire /etc/cron.d , /etc/cron.{hourly,daily,weekly,monthly} doit :

  • être détenu par la racine
  • être accessible en écriture uniquement par l'utilisateur root
  • ne pas être accessible en écriture par le groupe ou d'autres utilisateurs
  • ont un nom sans les points '. ou tout autre caractère spécial autre que '-' et '_' .

Le dernier blesse régulièrement les utilisateurs peu méfiants ; en particulier tout script dans un de ces dossiers nommé whatever.sh , mycron.py , testfile.pl etc. no être exécuté, jamais.

D'après mon expérience, ce point particulier est de loin la raison la plus fréquente d'un cronjob non exécuté sur Debian et ses dérivés.

Voir man cron pour plus de détails, si nécessaire.

23voto

Munkeh72 Points 319

Si vos cronjobs ne fonctionnent plus, vérifiez que votre mot de passe n'a pas expiré, car une fois qu'il a expiré, tous les cronjobs s'arrêtent.
Il y aura des messages dans /var/log/messages similaire à celui ci-dessous qui montre des problèmes avec l'authentification de l'utilisateur :

(username) FAILED to authorize user with PAM (Authentication token is no longer valid; new one required)

3 votes

Je viens également de recevoir ce message (fichier de message d'erreur /var/log/syslog pour moi). Dans mon cas, il s'agit d'une boîte DigitalOcean qui, au moment de la création, réinitialise le mot de passe root (facultatif) sur un autre mot de passe, et apparemment, tant que vous n'y allez pas pour le changer, toutes les tâches cron ne s'exécutent pas. C'est dommage. La solution est quelque chose comme sudo -u root passwd

19voto

snowdude Points 2790

Horaires peu fréquents et irréguliers

Cron est en somme un programmateur très basique et la syntaxe ne permet pas facilement à un administrateur de formuler des programmations un peu plus inhabituelles.

Considérez le travail suivant qui serait généralement expliqué à "courir command toutes les 5 minutes" :

*/5 * * * * /path/to/your/command

contre :

*/7 * * * * /path/to/your/command

dont n'est pas toujours exécuter command toutes les 7 minutes .

N'oubliez pas que le / peut être utilisé pour introduire une étape mais que les étapes ne se prolongent pas au-delà de la fin d'une série, par ex. */7 qui correspond à toutes les 7 minutes des minutes 0-59 c'est-à-dire 0,7,14,21,28,35,42,49,56 mais entre une heure et l'autre il y aura seulement 4 minutes entre les lots après 00:56 une nouvelle série commence à 01:00 , 01:07 etc. (et les lots ne fonctionneront pas sur 01:03 , 01:10 , 01:17 etc.).


Que faire à la place ?

Créer des lots multiples

Plutôt qu'une seule tâche cron, créez plusieurs lots qui, combinés, donnent le programme souhaité.

Par exemple, pour exécuter un lot toutes les 40 minutes (00:00, 00:40, 01:20, 02:00 etc.), créez deux lots, l'un qui s'exécute deux fois aux heures paires et l'autre qui s'exécute uniquement aux heures impaires :

# The following lines create a batch that runs every 40 minutes i.e.

# runs on   0:00, 0:40,        02:00, 02:40         04:00 etc to 22:40
0,40 */2 * * * /path/to/your/command

# runs on               01:20,               03:20,       etc to 23:20
20 1/2 * * * /path/to/your/command

# Combined: 0:00, 0:40, 01:20, 02:00, 02:40, 03:20, 04:00 etc.

Faites vos lots moins souvent

Au lieu d'exécuter votre lot toutes les 7 minutes, ce qui est un programme difficile à décomposer en plusieurs lots, exécutez-le simplement toutes les 10 minutes.

Commencez vos fournées plus fréquemment (mais empêche l'exécution simultanée de plusieurs lots)

De nombreux programmes bizarres évoluent parce que les durées d'exécution des lots augmentent ou fluctuent, puis les lots sont programmés avec une marge de sécurité supplémentaire pour éviter que les exécutions ultérieures du même lot ne se chevauchent et ne fonctionnent simultanément.

Au lieu de cela, pensez différemment et créez un cronjob qui échouera gracieusement lorsqu'une exécution précédente n'est pas encore terminée, mais qui s'exécutera sinon. Voir ce qui suit QUESTIONS ET RÉPONSES :

* * * * * /usr/bin/flock -n /tmp/fcj.lockfile /usr/local/bin/frequent_cron_job 

Cela lancera presque immédiatement une nouvelle exécution une fois que l'exécution précédente de /usr/local/bin/frequent_cron_job sera terminée.

Commencez vos fournées plus fréquemment (mais se termine de manière élégante lorsque les conditions ne sont pas réunies).

La syntaxe de cron étant limitée, vous pouvez décider de placer des conditions et une logique plus complexes dans le travail par lots lui-même (ou dans un script enveloppant autour du travail par lots existant). Cela vous permet d'utiliser les capacités avancées de vos langages de script préférés, de commenter votre code et d'éviter les constructions difficiles à lire dans l'entrée crontab elle-même.

Dans bash, le seven-minute-job ressemblerait alors à quelque chose comme ça :

#!/bin/bash
# seven-minute-job
# This batch will only run when 420 seconds (7 min) have passed
# since the file /tmp/lastrun was either created or updated

if [ ! -f /tmp/lastrun ] ; then
    touch /tmp/lastrun
fi

if [ $(( $(date +%s) - $(date -r /tmp/lastrun +%s) )) -lt 420 ] ; then
     # The minimum interval of 7 minutes between successive batches hasn't passed yet.
    exit 0
fi

####  Start running your actual batch job below

/path/to/your/command

#### actual batch job is done, now update the time stamp
date > /tmp/lastrun
#EOF

Que vous pouvez ensuite (tenter) d'exécuter toutes les minutes en toute sécurité :

* * * * * /path/to/your/seven-minute-job

Un problème différent, mais similaire, consisterait à programmer l'exécution d'un lot le premier lundi de chaque mois (ou le deuxième mercredi), etc. Il suffit de programmer le lot pour qu'il s'exécute tous les lundis et de le quitter lorsque la date n'est pas comprise entre les chiffres 1 et 2. st ou 7 th et le jour de la semaine n'est pas le lundi.

#!/bin/bash
# first-monday-of-the-month-housekeeping-job

# exit if today is not a Monday (and prevent locale issues by using the day number) 
if [ $(date +%u) != 1 ] ; then
  exit 0
fi

# exit if today is not the first Monday
if [ $(date +%d) -gt 7 ] ; then
  exit 0
fi

####  Start running your actual batch job below

/path/to/your/command

#EOF

Que vous pouvez ensuite, en toute sécurité, (tenter) d'exécuter chaque lundi :

0 0 * * 1 /path/to/your/first-monday-of-the-month-housekeeping-job

N'utilisez pas cron

Si vos besoins sont complexes, vous pouvez envisager d'utiliser un produit plus avancé, conçu pour exécuter des programmes complexes (distribués sur plusieurs serveurs) et qui prend en charge les déclencheurs, les dépendances de tâches, la gestion des erreurs, les tentatives et le suivi des tentatives, etc. Dans le jargon du secteur, on parle d'"entreprise". planification des tâches et/ou "automatisation de la charge de travail".

8voto

gaRex Points 386

Spécifique à PHP

Si vous avez une tâche cron comme :

php /bla/bla/something.php >> /var/logs/somelog-for-stdout.log

Et en cas d'erreurs, attendez-vous à ce qu'elles vous soient envoyées, mais elles ne le sont pas - vérifiez ceci.

Par défaut, PHP n'envoie pas les erreurs à STDOUT. @voir https://bugs.php.net/bug.php?id=22839

Pour résoudre ce problème, ajoutez dans le php.ini de votre client ou dans votre ligne (ou dans votre wrapper bash pour PHP) ce qui suit :

  • --definir display_startup_errors=1
  • --definir display_errors='stderr' (erreur de frappe)

Le premier paramètre vous permettra d'avoir des messages fatals comme 'Memory oops' et le second -- de les rediriger tous vers STDERR. Ce n'est qu'après que vous pourrez dormir sur vos deux oreilles car tout sera envoyé à la messagerie de votre root au lieu d'être simplement enregistré.

2 votes

Ce rapport d'erreur a été fermé en 2007 et le correctif a été ajouté aux branches de PHP 5.2+. Êtes-vous sûr que c'est nécessaire ? Je viens d'essayer avec PHP 5.4 et cela semble fonctionner correctement. (Il est toujours nécessaire pour PHP 4).

0 votes

@Xeoncross voir la date de la réponse :)

1 votes

Oui, c'est ce qui m'a troublé puisque vous avez répondu en 2013 et que le billet date de 2007.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X