web-dev-qa-db-fra.com

Cron et virtualenv

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.

203
John-Scott

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
225
ars

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/

88
DavidWinterbottom

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

10
Basil Musa

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...]
10
joemaller

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
9
Ivanhoe

La meilleure solution pour moi était à la fois

  • utilisez le binaire python dans le répertoire venv bin /
  • définissez le chemin python pour inclure le répertoire des modules venv.

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
>>>
3
here

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.

2
Dmitriy