Cron и virtualenv

Я пытаюсь запустить команду управления Django из cron. Я использую virtualenv, чтобы мой проект был изолирован.

Я видел примеры здесь и в других местах, которые показывают выполнение команд управления из virtualenv, таких как:

0 3 * * * source /home/user/project/env/bin/activate && /home/user/project/manage.py command arg

однако, хотя syslog показывает запись, когда задача должна была начаться, эта задача никогда не запускается (файл журнала для скрипта пуст). Если я запускаю строку вручную из оболочки, она работает так, как ожидалось.

единственный способ, которым я могу в настоящее время получить команду для запуска через cron, - это разбить команды и поместить их в тупой сценарий оболочки bash:

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

EDIT:

ars придумал рабочую комбинацию команд:

0 3 * * * cd /home/user/project && /home/user/project/env/bin/python /home/user/project/manage.py command arg

по крайней мере, в моем случае вызов сценария активации для virtualenv ничего не сделал. Это работает, так что с шоу.

7 ответов


вы должны быть в состоянии сделать это с помощью python в виртуальной среде:

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

EDIT: если ваш проект django не находится в PYTHONPATH, вам нужно переключиться в правильный каталог:

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

вы также можете попытаться зарегистрировать сбой из cron:

cd /home/my/project && /home/my/virtual/bin/python /home/my/project/manage.py > /tmp/cronlog.txt 2>&1

еще одна вещь, чтобы попытаться сделать то же самое изменение в вашем manage.py скрипт в самом верху:

#!/home/my/virtual/bin/python

под управлением source из файла cronfile не будет работать, поскольку cron использует /bin/sh в качестве оболочки по умолчанию, который не поддерживает source. Вам нужно установить переменную среды оболочки как /bin/bash:

SHELL=/bin/bash
*/10 * * * * root source /path/to/virtualenv/bin/activate && /path/to/build/manage.py some_command > /dev/null

это сложно определить, почему это не так /var/log/syslog не регистрирует сведения об ошибке. Лучше всего псевдоним себя root, так что вы получите по электронной почте с любыми ошибками cron. Просто добавьте себя в /etc/aliases и работать sendmail -bi.

Подробнее здесь: http://codeinthehole.com/archives/43-Running-django-cronjobs-within-a-virtualenv.html


вместо того, чтобы возиться с virtualenv-специфическими shebangs, просто добавьтеPATH на crontab.

из активированного virtualenv запустите эти три команды, и скрипты python должны просто работать:

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

первая строка crontab теперь должна выглядеть так:

PATH=/home/me/virtualenv/bin:/usr/bin:/bin:  # [etc...]

единственный правильный способ запуска заданий cron python при использовании virtualenv-активировать среду, а затем выполнить python среды для запуска кода.

один из способов сделать это-использовать virtualenv activate_this в вашем скрипте python см.: http://virtualenv.readthedocs.org/en/latest/userguide.html#using-virtualenv-without-bin-python

другое решение повторяет полную команду, включая активацию окружающей среды и ее транспортировку в /bin/bash. Рассмотрим это для вашего /etc/crontab:

***** root echo 'source /env/bin/activate; python /your/script' | /bin/bash

не смотрите дальше:

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

общий подход:

* * * * * /usr/bin/env bash -c 'YOUR_COMMAND_HERE' > /dev/null 2>&1

красота об этом вам не нужно менять SHELL переменная для crontab из sh to bash


лучшее решение для меня было для обоих

  • используйте двоичный файл python в каталоге venv bin/
  • задайте путь python чтобы включить каталог модулей venv.

man python упоминает изменение пути в оболочке в $PYTHONPATH или в python с sys.path

другие ответы упоминают идеи для этого с помощью оболочки. Из python добавление следующих строк в мой скрипт позволяет мне успешно запускать его непосредственно из демон cron.

import sys
sys.path.insert(0,'/path/to/venv/lib/python3.3/site-packages');

вот как это выглядит в интерактивном сеансе --

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

Я хотел бы добавить это, потому что я потратил некоторое время на решение проблемы и не нашел ответа здесь для использования комбинации переменных в cron и virtualenv. Может, это кому-то поможет.

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

Он не работал хорошо, когда он был настроен как

DIR_SMTH= " cd / smth && . venv/bin/активировать"

спасибо @davidwinterbottom, @reed-sandberg и @mkb за предоставление права направление. Принятый ответ на самом деле работает нормально, пока вашему python не нужно запустить скрипт, который должен запустить другой двоичный файл python из каталога venv/bin.