2010-07-20 2 views
161

Я пытаюсь запустить команду управления Django из cron. Я использую virtualenv для сохранения моего проекта в песочнице.Cron and virtualenv

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

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

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

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

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

EDIT:

АРС придумал с рабочей комбинации команд:

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

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

+0

Одно различие, которое я вижу в том, что скрипт будет работать manage.py с/главная/пользователя/проекта в качестве текущего рабочего каталога. Ваша команда cron будет запущена с вашим домашним каталогом как cwd. Может быть, файл журнала есть? – rettops

+0

Фактически путь журнала определен абсолютно, он просто не создан/добавлен, потому что скрипт не запущен. –

+0

Быстрое и грязное решение проблем cron - это сброс вашей среды (в которой ваша команда необъяснимо работает) с 'env' и' export' их всех в оболочке сценария bash, которую вы вызываете из crontab. – jberryman

ответ

170

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

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

EDIT: Если ваш Джанго проект не в PYTHONPATH, то вам нужно перейти вправо каталог:

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

Вы также можете попытаться войти отказ от хрон:

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

это тоже не работает. Забыл положить это в мой список вещей, которые не работают. Да, я могу запустить эту команду вручную в оболочке, но она не работает из cron. –

+0

Вы заменили '~' полным путем? (Вы, наверное, сделали это, просто убедившись ...) – ars

+0

А, вы придумали рабочий пример! Я пробовал каждую комбинацию, и активирование virtualenv, похоже, не имеет никакого эффекта. Я устанавливаю PYTHONPATH в .bashrc, но это, по-видимому, не используется cron? Будет обновлен мой вопрос, чтобы подчеркнуть ваш ответ. –

64

Запуск source из cronfile не будет работать, как хрон использует /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

+9

Или '.' (команда точка), которая поддерживается/bin/sh'./path/to/virtualenv/bin/activate' –

+4

DavidWinterbottom, если это ваше настоящее имя, вы мой герой. Я никогда не знал этого о sh vs bash и исходных файлах. Вы зажгли свет в моем маленьком чуваке, пишущем сценарий. Благодарю. – joemurphy

+0

Если у вас есть файл 'postactivate', вы должны делать' source/path/to/virtualenv/bin/activate && source/path/to/virtualenv/bin/postactivate' – dspacejs

11

Вместо отводом вокруг с virtualenv конкретных shebangs, просто предварять PATH на кронтаб.

С активированной virtualenv, запустить эти три команды и Python скрипты должны просто работать:

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

первая линия CRONTAB должна выглядеть следующим образом:

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

Не очень хорошее решение. Тогда все задачи python в crontab будут запускаться с бинарником из virtualenv. Создание этого двоичного _pseudo-global_ python идет вразрез с самой целью virtualenv. –

7

Единственный правильный способ запуска Задачи 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 
+0

Мне очень любопытно, есть ли консенсус в том, что это на самом деле единственный правильный путь. –

+0

Это, вероятно, единственный правильный путь. Но есть и другие способы, которые работают. – Will

+2

Это не «единственный правильный путь». Я успешно выполнил сценарий в virtualenv, просто указав cronjob на бинарный файл python virtualenv, например '/ home/user/folder/env/bin/python'. Не нужно активировать окружающую среду. – tracicot

1

Лучшее решение для меня было как

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

man python упоминает изменения пути в оболочке на $PYTHONPATH или питоне с 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 
>>>