Question Pourquoi ma crontab ne fonctionne-t-elle pas et comment puis-je la résoudre?


C'est un Question canonique à propos de l'utilisation de cron & crontab.

Vous avez été dirigé ici parce que la communauté est à peu près certaine que la réponse à votre question se trouve ci-dessous. Si votre question ne répond pas ci-dessous, elle vous aidera à rassembler des informations qui aideront la communauté à vous aider. Cette information devrait être modifiée dans votre question initiale.

La réponse pour 'Pourquoi ma crontab ne fonctionne-t-elle pas et comment puis-je la résoudre?'peut être vu ci-dessous. Cela concerne le cron système avec la crontab en surbrillance.


193
2017-11-17 04:51


origine


C'est une énorme dupe de Raisons pour lesquelles crontab ne fonctionne pas sur AskUbuntu. - Dan Dascalescu


Réponses:


Comment résoudre tous vos problèmes / problèmes liés à crontab (Linux)


C'est un wiki de la communauté, si vous remarquez quelque chose d’erreur avec cette réponse ou si vous avez des informations supplémentaires, modifiez-les.


Premièrement, la terminologie de base:

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

Ensuite, éducation sur cron:

Chaque utilisateur d’un système peut avoir son propre fichier crontab. L'emplacement des fichiers crontab racine et utilisateur dépend du système, mais ils sont généralement inférieurs à /var/spool/cron.

Il y a un système /etc/crontab fichier, le /etc/cron.d Le répertoire peut contenir des fragments de crontab qui sont également lus et gérés par cron. Certaines distributions Linux (par exemple, Red Hat) ont également /etc/cron.{hourly,daily,weekly,monthly} qui sont des répertoires, des scripts dans lesquels seront exécutés toutes les heures / jours / semaines / mois, avec le privilège root.

root peut toujours utiliser la commande crontab; les utilisateurs réguliers peuvent ou non recevoir un accès. Lorsque vous éditez le fichier crontab avec la commande crontab -e et enregistrez-le, crond le vérifie pour la validité de base mais ne garantit pas que votre fichier crontab est correctement formé. Il y a un fichier appelé cron.deny qui spécifiera quels utilisateurs ne peuvent pas utiliser cron. le 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 allumé ou si le démon crond n'est pas en cours d'exécution et que la date / heure d'exécution d'une commande est expirée, crond n'acceptera pas et n'exécutera pas les requêtes antérieures.

Détails 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 hash (#) signe représente un commentaire qui signifie que tout ce qui est sur cette ligne est ignoré par cron. Les espaces et les lignes vierges sont ignorés.

Soyez très prudent lorsque vous utilisez le pourcentage (%) connectez-vous à votre commande. À moins qu'ils ne soient échappés \% ils sont convertis en newlines et tout après le premier non échappé % est passé à votre commande sur stdin.

Il existe deux formats pour les fichiers crontab:

  • Crontabs utilisateur

    # 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
    
  • À l'échelle du système /etc/crontab et /etc/cron.d des 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 nécessite un nom d'utilisateur. La commande sera exécutée en tant qu'utilisateur nommé.

Les 5 premiers champs de la ligne représentent l'heure à laquelle la commande doit être exécutée. Vous pouvez utiliser des chiffres ou des noms de jours / mois, le cas échéant, 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 courir à 1,4,6,8.
  • Les plages sont spécifiées 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.
  • le / le caractère peut être utilisé pour introduire une étape, par exemple. 2/5 ce qui signifie à partir de 2 puis de tous les 5 (2,7,12,17,22 ...). Ils ne vont pas au-delà de la fin.
  • Un astérisque (*) dans un champ signifie la plage entière de ce champ (par exemple, 0-59 pour le champ des minutes).
  • Les plages et les étapes peuvent être combinées, par exemple. */2 signifie à partir du minimum pour le champ concerné, puis tous les 2 ex. 0 pour les minutes (0,2 ... 58), 1 pour les mois (1,3 ... 11) etc.

Débogage des commandes cron

Vérifiez le mail! Par défaut, cron enverra toute sortie de la commande à l'utilisateur sur lequel elle est exécutée. S'il n'y a pas de sortie, il n'y aura pas de courrier. Si vous voulez que cron envoie des messages à un autre compte, vous pouvez définir la variable d’environnement MAILTO dans le fichier crontab, par exemple.

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

Capturez vous-même la sortie

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

qui capture stdout et stderr dans /tmp/mycommand.log

Regardez les bûches. cron enregistre ses actions via syslog, qui (selon votre configuration) va souvent à /var/log/cron ou /var/log/syslog.

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

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 obtenir quelque chose comme

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

ou

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

Si ce n'est pas le redémarrer

/sbin/service cron start

ou

/sbin/service crond start

Il peut y avoir d'autres méthodes; utilisez ce que votre distribution fournit.

cron exécute votre commande dans un environnement restreint.

Les variables d'environnement disponibles sont susceptibles d'être très limitées. Généralement, vous ne définissez que quelques variables, telles que $LOGNAME, $HOME, et $PATH.

Il convient de noter le PATH est limité à /bin:/usr/bin. La grande majorité des problèmes "mon script cron ne fonctionne pas" sont causés par ce chemin restrictif. Si votre commande est dans un emplacement différent, vous pouvez résoudre ce problème de plusieurs manières:

  1. Indiquez le chemin complet de votre commande.

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

    PATH=/usr:/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

Peu importe 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 sera exécuté sera le répertoire personnel de l'utilisateur. Si vous accédez aux fichiers de votre programme, vous devrez en tenir compte si vous utilisez des chemins relatifs, ou (de préférence), utilisez simplement des chemins pleinement qualifiés partout, ce qui évite à tout le monde beaucoup de confusion.

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

Cron nécessite 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érifier le format de la crontab

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

Je mets un fichier dans /etc/cron.{hourly,daily,weekly,monthly} et il ne s'exécute pas

  • Vérifiez que le nom du fichier n’a pas d’extension voir run-parts
  • Assurez-vous que le fichier dispose des autorisations d'exécution.
  • Indiquez au système quoi utiliser lors de l’exécution de votre script (par exemple, put #!/bin/sh en haut)

Bugs liés à la date de Cron

Si votre date est récemment modifiée par un utilisateur ou une mise à jour du système, un fuseau horaire ou autre, crontab commencera à se comporter de manière erratique et affichera des bugs bizarres, parfois fonctionnels, parfois non. C'est la tentative de crontab d'essayer de "faire ce que vous voulez" quand le temps change de dessous. 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 à Internet (pour que la date ne puisse pas être réinitialisée sur l'un des serveurs de temps).

Encore des signes de pourcentage

Pour souligner le conseil relatif aux signes de pourcentage, voici un exemple de ce que cron en fait:

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

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

foo
bar
baz

Ceci est particulièrement intrusif lorsque vous utilisez le date commander. Assurez-vous d'échapper aux signes de pourcentage

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

273
2017-10-09 15:29



Vous voudrez peut-être aussi mentionner dans la section «Env. Restreint» que LD_LIBRARY_PATH peut également avoir besoin de définir des répertoires supplémentaires au cas où votre tâche périodique échouerait du fait de l'impossibilité de trouver des bibliothèques partagées. - DavidJ
notez que vous pouvez même écrire quelque chose comme ceci: 35 1,5-23 / 2 * * * do_something au lieu de 35,1,5,7,9, .. * * * De plus, cela crontab.guru traduit vos entrées en langage humain. - Dennis Nolte
La capture en 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 - chus
cela a fonctionné pour moi: sudo apt-get install postfix - jmunsch
Le travail de cron dépend-il également de la lourdeur du fichier? Parce que j'ai couru le monde simple bonjour en python avec le cron, cela a fonctionné. Mais mon deuxième code était un peu lourd et fonctionne normalement, mais avec cron, il ne donne aucune sortie dans le fichier. - Devendra Bhat


Si vos tâches cron cessent de fonctionner, vérifiez que votre mot de passe n’a pas expiré. Depuis, tous les travaux cron s’arrêtent.
Il y aura des messages dans /var/log/messages similaire à celui ci-dessous qui montre des problèmes d'authentification de l'utilisateur:

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


18
2018-02-04 20:29



Je viens également de l’obtenir (fichier de messages d’erreur / var / log / syslog pour moi). Dans mon cas, une boîte DigitalOcean qui, au moment de la création, réinitialise le mot de passe root (éventuellement) en un autre, et apparemment jusqu'à ce que vous y apportiez des modifications, toutes les tâches cron ne s'exécutent pas. Bummer. Fix est quelque chose comme sudo -u root passwd - rogerdpack


Debian Linux et ses dérivés (Ubuntu, Mint, etc.) présentent certaines particularités qui peuvent empêcher votre tâche cron de s’exécuter. en particulier, les fichiers dans /etc/cron.d, /etc/cron.{hourly,daily,weekly,monthly} doit :

  • être la propriété de root
  • être seulement accessible en écriture par root
  • ne pas être accessible en écriture par le groupe ou d'autres utilisateurs
  • avoir un nom sans points "." ou tout autre caractère spécial sauf '-' et '_'.

Le dernier fait régulièrement mal aux utilisateurs peu méfiants; en particulier tout script dans l'un de ces dossiers nommés whatever.sh, mycron.py, testfile.pletc. seront ne pas être exécuté, jamais.

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

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


15
2017-11-17 14:37





Horaires peu communs et irréguliers

Cron est tout à fait considéré comme un ordonnanceur très basique et la syntaxe ne permet pas facilement à un administrateur de formuler des plannings légèrement plus rares.

Considérez le travail suivant qui serait communément expliqué à "courir command toutes les 5 minutes ":

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

contre:

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

lequel ne fait pas toujours courir command toutes les 7 minutes.

Rappelez-vous que le / Le caractère peut être utilisé pour introduire une étape, mais ces étapes ne se terminent pas au-delà de la fin d'une série, par ex. */7 qui correspond à toutes les 7 minutes des minutes 0-59  à savoir 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 plusieurs lots

Plutôt que de créer un seul travail cron, créez plusieurs lots qui, combinés, donnent le planning 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, un qui s'exécute deux fois aux heures paires et l'autre qui ne fonctionne qu'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.

Exécutez vos lots moins fréquemment 

Plutôt que 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.

Exécutez vos lots plus fréquemment 

De nombreuses planifications étranges évoluent car les durées d'exécution des lots augmentent / fluctuent, puis les lots sont planifiés avec une marge de sécurité supplémentaire afin d'éviter que les exécutions ultérieures du même lot ne se chevauchent et ne s'exécutent simultanément.

Au lieu de cela, pensez différemment et créez un cronjob qui échouera de manière élégante lorsqu'une exécution précédente n'est pas encore terminée, mais qui s'exécutera autrement. Regarde ça Q & A:

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

Sur une note similaire, vous pouvez enregistrer par lots l'enregistrement de l'horodatage de la dernière exécution réussie et au début de la vérification par lots si l'intervalle souhaité entre les lots est déjà passé et s'exécute ou quitte normalement.

En bas le seven-minute-job ressemblerait à quelque chose comme:

#!/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
    echo "The minimum interval of 7 minutes between successive batches hasn't passed yet."
    exit
fi

echo "Start running your batch"

date > /tmp/lastrun

Ce que vous pouvez alors en toute sécurité (tenter) de lancer toutes les minutes:

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

Ne pas utiliser cron

Si vos besoins sont complexes, vous pouvez envisager d’utiliser un produit plus avancé conçu pour exécuter des planifications complexes (réparties sur plusieurs serveurs) et prenant en charge les déclencheurs, les dépendances de tâches, la gestion des erreurs, la surveillance des tentatives, etc. Le jargon de l’industrie est "entreprise". ordonnancement des travaux et / ou "automatisation de la charge de travail".


10
2017-10-23 04:45





Spécifique à PHP

Si vous avez un job cron comme:

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

Et en cas d'erreur, attendez-vous à ce qu'ils vous soient envoyés, mais ils ne le font pas - vérifiez ceci.

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

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

  • --define display_startup_errors = 1
  • --define display_errors = 'stderr'

Le 1er réglage vous permettra d'avoir des fatals du genre 'Memory oops' et 2nd - de les rediriger tous vers STDERR. Ce n’est qu’après avoir bien dormi que tout sera envoyé au courrier de votre racine au lieu d’être simplement connecté.


8



Ce rapport d'erreur a été fermé en 2007 avec le statut du correctif ajouté aux branches PHP 5.2+. Êtes-vous sûr que c'est nécessaire? Je viens d'essayer sur PHP 5.4 et cela semble fonctionner correctement. (Il est toujours nécessaire pour PHP 4 cependant). - Xeoncross
@Xeoncross voir date de réponse :) - gaRex
Oui, c'est ce qui m'a dérouté depuis que vous avez répondu en 2013 et que le billet était de retour en 2007. - Xeoncross