WTF ? ! Mon cronjob ne s'exécute pas ? !
Voici un guide de liste de contrôle pour déboguer sans exécuter les cronjobs :
- Le démon Cron est-il en cours d'exécution ?
- Exécuter
ps ax | grep cron
et recherchez cron. - Debian :
service cron start
ouservice cron restart
- Cron fonctionne-t-il ?
* * * * * /bin/echo "cron works" >> /tmp/file
- Syntaxe correcte ? Voir ci-dessous.
- Vous devez évidemment avoir un accès en écriture au fichier vers lequel vous redirigez la sortie. Un nom de fichier unique en
/tmp
qui n'existe pas actuellement doit toujours être accessible en écriture. - Ajouter probablement aussi
2>&1
pour inclure l'erreur standard ainsi que la sortie standard, ou sortir séparément l'erreur standard dans un autre fichier avec2>>/tmp/errors
- La commande fonctionne-t-elle de manière autonome ?
- Vérifiez si le script contient une erreur en effectuant un essai sur la CLI
- Lorsque vous testez votre commande, testez en tant qu'utilisateur dont vous modifiez la crontab, qui peut ne pas être votre login ou root
- Cron peut-il exécuter votre tâche ?
- Vérifier
/var/log/cron.log
ou/var/log/messages
pour les erreurs. - Ubuntu :
grep CRON /var/log/syslog
- Redhat :
/var/log/cron
- Vérifier les autorisations
- Définir l'indicateur d'exécutable sur la commande :
chmod +x /var/www/app/cron/do-stuff.php
- Si vous redirigez la sortie de votre commande vers un fichier, vérifiez que vous êtes autorisé à écrire dans ce fichier/répertoire
- Vérifier les chemins
- Vérifier la ligne she-bangs/hashbangs
- Ne vous fiez pas aux variables d'environnement comme
PATH
, car leur valeur ne sera probablement pas la même sous cron que sous une session interactive. Voir Comment faire en sorte que CRON appelle les bons PATH
- Ne supprimez pas la sortie pendant le débogage
- Cette suppression est couramment utilisée :
30 1 * * * command > /dev/null 2>&1
- Réactivez la sortie standard ou la sortie de message d'erreur standard en supprimant
>/dev/null 2>&1
tout à fait; ou peut-être rediriger vers un fichier dans un emplacement où vous avez un accès en écriture :>>cron.out 2>&1
ajoutera la sortie standard et l'erreur standard àcron.out
dans le répertoire personnel de l'utilisateur appelant. - Si vous ne redirigez pas la sortie d'un
cron
job, le démon essaiera de vous envoyer tout message de sortie ou d'erreur par e-mail. Vérifiez votre boîte de réception (peut-être simplementmore $MAIL
si vous n'avez pas de client de messagerie). Si le courrier n'est pas disponible, recherchez peut-être un fichier nommédead.letter
dans votre répertoire personnel ou des entrées de journal système indiquant que la sortie a été supprimée. Surtout dans ce dernier cas, éditez probablement la tâche pour ajouter une redirection vers un fichier, puis attendez que la tâche s'exécute et examinez le fichier journal à la recherche de messages d'erreur ou d'autres commentaires utiles. - Si vous essayez de comprendre pourquoi quelque chose a échoué, les messages d'erreur seront visibles dans ce fichier. Lisez-le et comprenez-le.
Ne fonctionne toujours pas ? Aïe !
- Augmenter le niveau de débogage cron
- Debian
- en
/etc/default/cron
- définir
EXTRA_OPTS="-L 2"
service cron restart
tail -f /var/log/syslog
pour voir les scripts exécutés
- en
- Ubuntu
- en
/etc/rsyslog.d/50-default.conf
- ajouter ou commenter la ligne
cron.* /var/log/cron.log
- recharger l'enregistreur
sudo /etc/init.d/rsyslog restart
- réexécuter cron
- ouvrir
/var/log/cron.log
et recherchez une sortie d'erreur détaillée
- en
- Rappel :désactivez le niveau de journalisation lorsque vous avez terminé le débogage
- Exécutez cron et vérifiez à nouveau les fichiers journaux
Syntaxe des tâches cron
# Minute Hour Day of Month Month Day of Week User Command
# (0-59) (0-23) (1-31) (1-12 or Jan-Dec) (0-6 or Sun-Sat)
0 2 * * * root /usr/bin/find
Cette syntaxe est seulement correct pour le root
utilisateur. Utilisateur régulier crontab
la syntaxe n'a pas le Utilisateur champ (les utilisateurs réguliers ne sont pas autorisés à exécuter du code comme n'importe quel autre utilisateur) ;
# Minute Hour Day of Month Month Day of Week Command
# (0-59) (0-23) (1-31) (1-12 or Jan-Dec) (0-6 or Sun-Sat)
0 2 * * * /usr/bin/find
Commandes Crontab
crontab -l
- Répertorie toutes les tâches cron de l'utilisateur.
crontab -e
, pour un utilisateur spécifique :crontab -e -u agentsmith
- Démarre la session d'édition de votre fichier crontab.
- Lorsque vous quittez l'éditeur, la crontab modifiée est automatiquement installée.
crontab -r
- Supprime votre entrée crontab du spouleur cron, mais pas du fichier crontab.
Je veux ajouter 2 points que j'ai appris :
- Les fichiers de configuration Cron placés dans /etc/cron.d/ ne doivent pas contenir de point (.). Sinon, il ne sera pas lu par cron.
- Si l'utilisateur qui exécute votre commande n'est pas dans /etc/shadow. Il ne sera pas autorisé à programmer cron.
Références :
- http://manpages.ubuntu.com/manpages/xenial/en/man8/cron.8.html
- https://help.ubuntu.com/community/CronHowto
Enfin j'ai trouvé la solution. Voici la solution :-
-
N'utilisez jamais de chemin relatif dans les scripts python à exécuter via crontab. J'ai fait quelque chose comme ceci à la place :-
import os import sys import time, datetime CLASS_PATH = '/srv/www/live/mainapp/classes' SETTINGS_PATH = '/srv/www/live/foodtrade' sys.path.insert(0, CLASS_PATH) sys.path.insert(1,SETTINGS_PATH) import other_py_files
-
Ne supprimez jamais le code crontab, utilisez plutôt le serveur de messagerie et vérifiez le courrier de l'utilisateur. Cela donne un aperçu plus clair de ce qui se passe.
Une autre raison pour laquelle crontab échouera :traitement spécial du %
caractère.
À partir du fichier manuel :
The entire command portion of the line, up to a newline or a
"%" character, will be executed by /bin/sh or by the shell specified
in the SHELL variable of the cronfile. A "%" character in the
command, unless escaped with a backslash (\), will be changed into
newline characters, and all data after the first % will be sent to
the command as standard input.
Dans mon cas particulier, j'utilisais date --date="7 days ago" "+%Y-%m-%d"
pour produire des paramètres pour mon script, et il échouait silencieusement. J'ai finalement découvert ce qui se passait quand j'ai vérifié syslog
et j'ai vu que ma commande était tronquée au %
symbole. Vous devez y échapper comme ceci :
date --date="7 days ago" "+\%Y-\%m-\%d"
Voir ici pour plus de détails :
http://www.ducea.com/2008/11/12/using-the-character-in-crontab-entries/