Cron et virtualenv

j'essaie d'exécuter un ordre de gestion de Django de cron. J'utilise virtualenv pour garder mon projet dans un bac à sable.

j'ai vu des exemples ici et ailleurs qui montrent comment exécuter des commandes de gestion à partir de virtualenv comme:

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 lorsque la tâche aurait dû commencer, cette tâche ne s'exécute jamais (le fichier journal du script est vide). Si j'exécute la ligne manuellement à partir de la coquille, il fonctionne comme prévu.

la seule façon dont je peux actuellement faire tourner la commande via cron, est de casser les commandes et de les mettre dans un script d'enveloppement de bash muet:

#!/bin/sh
source /home/user/project/env/bin/activate
cd /home/user/project/
./manage.py command arg

EDIT:

ars est venu avec une combinaison 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, invoquer le script d'activation pour le virtualenv n'a rien fait. Cela fonctionne, donc le spectacle.

174
demandé sur Francisco Couzo 2010-07-20 08:33:15

7 réponses

vous devriez pouvoir le faire en utilisant le python dans votre environnement virtuel:

/home/my/virtual/bin/python /home/my/project/manage.py command arg

éditer: si votre projet django n'est pas dans le PYTHONPATH, alors vous aurez besoin de passer au répertoire de droite:

cd /home/my/project && /home/my/virtual/bin/python ...

vous pouvez également essayer d'enregistrer l'échec de 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 de faire le même changement dans votre script manage.py en haut:

#!/home/my/virtual/bin/python
188
répondu ars 2011-09-09 22:27:32

exécuter source à partir d'un fichier Cron 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 comme étant /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 ne fonctionne pas, car /var/log/syslog n'enregistre pas les détails de l'erreur. Il est préférable de vous identifier vous-même pour root afin que vous obteniez par e-mail toutes les erreurs cron. Ajoutez simplement /etc/aliases et lancez sendmail -bi .

plus d'informations ici: http://codeinthehole.com/archives/43-Running-django-cronjobs-within-a-virtualenv.html

73
répondu DavidWinterbottom 2011-08-11 19:33:35

plutôt que de se moquer de shebangs virtualenv spécifiques, il suffit de prepend PATH sur le crontab.

à partir d'un virtualenv activé, exécutez ces trois commandes et les scripts python devraient simplement fonctionner:

$ echo "PATH=$PATH" > myserver.cron
$ crontab -l >> myserver.cron
$ crontab myserver.cron

la première ligne du crontab devrait maintenant ressembler à ceci:

PATH=/home/me/virtualenv/bin:/usr/bin:/bin:  # [etc...]
11
répondu joemaller 2012-12-12 04:42:01

la seule façon correcte d'exécuter des tâches en cron python lorsqu'on utilise un virtualenv est d'activer l'environnement et ensuite d'exécuter le code python de l'environnement.

une façon de le faire est d'utiliser le activate_this de virtualenv dans votre script python, voir: http://virtualenv.readthedocs.org/en/latest/userguide.html#using-virtualenv-without-bin-python

une autre solution fait écho à la commande complète incluant activation de l'environnement et canalisation dans /bin/bash . Considérez ceci pour votre /etc/crontab :

***** root echo 'source /env/bin/activate; python /your/script' | /bin/bash
8
répondu Ivanhoe 2015-03-27 23:34:44

Ne cherchez pas plus loin:

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é à ce sujet est que vous N'avez PAS besoin de changer le SHELL variable pour la crontab de sh à bash

3
répondu Basil Musa 2018-05-27 21:32:19

la meilleure solution pour moi était à la fois

  • utiliser le binaire python dans le bin/ répertoire venv
  • définit le chemin du python pour inclure le répertoire des modules venv.

man python mentions modifiant le chemin dans shell à $PYTHONPATH ou en python avec sys.path

D'autres réponses mentionnent des idées pour faire cela en utilisant le shell. De python, en ajoutant les lignes suivantes à mon script me permet de l'exécuter directement depuis 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
>>>
2
répondu here 2014-04-25 08:00:09

j'aimerais ajouter ceci parce que j'ai passé du temps à résoudre le problème et je n'ai pas trouvé de réponse ici pour la combinaison des variables usage dans cron et virtualenv. Alors peut-être que ça aidera 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 en fait très bien jusqu'à ce que votre python ait besoin d'exécuter un script qui doit exécuter un autre binaire python du répertoire venv/bin.

0
répondu Dmitriy 2018-08-08 15:26:50