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
РЕДАКТИРОВАТЬ:
ars придумали рабочую комбинацию команд:
0 3 * * * cd /home/user/project && /home/user/project/env/bin/python /home/user/project/manage.py command arg
По крайней мере, в моем случае вызов сценария активации для virtualenv ничего не сделал. Это работает, так и с шоу.
Ответы
Ответ 1
Вы должны сделать это, используя 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
script на самом верху:
#!/home/my/virtual/bin/python
Ответ 2
Запуск source
из cronfile не будет работать, поскольку cron использует /bin/sh
как свою оболочку по умолчанию, которая не поддерживает source
. Вы должны установить переменную среды SHELL равной /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
Ответ 3
Вместо того, чтобы трахаться с виртуальными вибэндами, просто добавьте 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...]
Ответ 4
Единственный правильный способ запуска заданий Python cron при использовании virtualenv - это активировать среду, а затем запустить среду python для запуска вашего кода.
Один из способов сделать это является использование virtualenv activate_this
в вашем питона сценарии см: 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
Ответ 5
Не смотрите дальше:
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
на bash
Ответ 6
Лучшее решение для меня было для обоих
- используйте двоичный код python в каталоге/каталоге venv
- установить путь python
для включения каталога модулей venv.
man python
упоминает изменение пути в оболочке в $PYTHONPATH
или в python с sys.path
В других ответах упоминаются идеи для этого, используя оболочку. Из python добавление следующих строк в мой script позволяет мне успешно запускать его непосредственно из 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
>>>
Ответ 7
Я хотел бы добавить это, потому что я потратил некоторое время на решение проблемы и не нашел здесь ответа на вопрос об использовании комбинации переменных в 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/activ"
Спасибо @davidwinterbottom, @reed-sandberg и @mkb за правильное направление. Принятый ответ на самом деле работает нормально, пока вашему питону не понадобится запустить скрипт, который должен запускать другой двоичный файл питона из каталога venv/bin.