J'essaie d'exécuter une commande de gestion Django de cron. J'utilise virtualenv pour conserver mon projet en sandbox.
J'ai vu des exemples ici et ailleurs montrant des commandes de gestion en cours d'exécution à partir de virtualenv telles que:
0 3 * * * source /home/user/project/env/bin/activate && /home/user/project/manage.py command arg
Cependant, même si syslog affiche une entrée au moment où la tâche aurait dû être lancée, cette tâche ne s'exécute jamais (le fichier journal du script est vide). Si je lance la ligne manuellement à partir du shell, cela fonctionne comme prévu.
La seule façon dont je peux actuellement obtenir la commande à exécuter via cron est de casser les commandes et de les placer dans un script dumb bash wrapper:
#!/bin/sh
source /home/user/project/env/bin/activate
cd /home/user/project/
./manage.py command arg
MODIFIER:
ars a mis au point une combinaison fonctionnelle de commandes:
0 3 * * * cd /home/user/project && /home/user/project/env/bin/python /home/user/project/manage.py command arg
Au moins dans mon cas, l'invocation du script d'activation pour virtualenv n'a rien donné. Cela fonctionne, ainsi de suite avec le spectacle.
Vous devriez pouvoir le faire en utilisant python
dans votre environnement virtuel:
/home/my/virtual/bin/python /home/my/project/manage.py command arg
EDIT: Si votre projet Django ne se trouve pas dans PYTHONPATH, vous devrez passer au bon répertoire:
cd /home/my/project && /home/my/virtual/bin/python ...
Vous pouvez également essayer de consigner l’échec depuis cron:
cd /home/my/project && /home/my/virtual/bin/python /home/my/project/manage.py > /tmp/cronlog.txt 2>&1
Une autre chose à essayer est d’apporter le même changement à votre manage.py
script tout en haut:
#!/home/my/virtual/bin/python
Lancer source
à partir d'un fichier cronfile ne fonctionnera pas car cron utilise /bin/sh
comme shell par défaut, qui ne supporte pas source
. Vous devez définir la variable d’environnement Shell sur /bin/bash
:
Shell=/bin/bash
*/10 * * * * root source /path/to/virtualenv/bin/activate && /path/to/build/manage.py some_command > /dev/null
Il est difficile de comprendre pourquoi cela échoue car /var/log/syslog
ne consigne pas les détails de l'erreur. Il est préférable de vous alias root pour pouvoir recevoir des erreurs cron par courrier électronique. Ajoutez-vous simplement à /etc/aliases
et courir sendmail -bi
.
Plus d'infos ici: http://codeinthehole.com/archives/43-Running-Django-cronjobs-within-a-virtualenv.html
le lien ci-dessus est remplacé par: https://codeinthehole.com/tips/running-Django-cronjobs-within-a-virtualenv/
Ne cherchez plus:
0 3 * * * /usr/bin/env bash -c 'cd /home/user/project && source /home/user/project/env/bin/activate && ./manage.py command arg' > /dev/null 2>&1
Approche générique:
* * * * * /usr/bin/env bash -c 'YOUR_COMMAND_HERE' > /dev/null 2>&1
La beauté de ceci est que vous n'avez PAS besoin de changer la variable Shell
de la crontab de sh
à bash
Plutôt que de bricoler avec des shebangs spécifiques à virtualenv, ajoutez simplement PATH
à la crontab.
Depuis un virtualenv activé, exécutez ces trois commandes et les scripts python devraient fonctionner:
$ echo "PATH=$PATH" > myserver.cron
$ crontab -l >> myserver.cron
$ crontab myserver.cron
La première ligne de la crontab devrait maintenant ressembler à ceci:
PATH=/home/me/virtualenv/bin:/usr/bin:/bin: # [etc...]
La seule façon correcte d'exécuter python) lorsque vous utilisez virtualenv est d'activer l'environnement, puis exécutez-la python pour exécuter votre code.
Une façon de faire est d’utiliser virtual _vactivate_this
dans votre python, voir: http://virtualenv.readthedocs.org/en/latest/userguide.html#using-virtualenv-without-bin-python
Une autre solution fait écho à la commande complète, y compris l’activation de l’environnement et sa canalisation dans /bin/bash
. Considérez ceci pour votre /etc/crontab
:
***** root echo 'source /env/bin/activate; python /your/script' | /bin/bash
La meilleure solution pour moi était à la fois
man python
mentionne la modification du chemin dans Shell à $PYTHONPATH
ou dans python avec sys.path
D'autres réponses mentionnent des idées pour le faire à l'aide de Shell. À partir de python, l’ajout des lignes suivantes à mon script me permet de l’exécuter avec succès directement à partir de cron.
import sys
sys.path.insert(0,'/path/to/venv/lib/python3.3/site-packages');
Voici à quoi ça ressemble dans une session interactive -
Python 3.3.2+ (default, Feb 28 2014, 00:52:16)
[GCC 4.8.1] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', '/usr/lib/python3.3', '/usr/lib/python3.3/plat-x86_64-linux-gnu', '/usr/lib/python3.3/lib-dynload']
>>> import requests
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'requests'
>>> sys.path.insert(0,'/path/to/venv/modules/');
>>> import requests
>>>
J'aimerais ajouter ceci parce que j'ai passé un certain temps à résoudre le problème et que je n'ai pas trouvé de réponse ici pour l'utilisation combinée de variables dans cron et virtualenv. Alors peut-être que ça va aider quelqu'un.
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DIR_SMTH="cd /smth"
VENV=". venv/bin/activate"
CMD="some_python_bin do_something"
# m h dom mon dow command
0 * * * * $DIR_SMTH && $VENV && $CMD -k2 some_target >> /tmp/crontest.log 2>&1
Cela ne fonctionnait pas bien quand il était configuré comme
DIR_SMTH = "cd/smth &&. Venv/bin/activate"
Merci @ davidwinterbottom , @ reed-sandberg et @ mkb pour avoir donné la bonne direction. La réponse acceptée fonctionne bien jusqu’à ce que votre python devez exécuter un script qui doit exécuter un autre python binaire à partir du répertoire venv/bin.