Cron i virtualenv

Próbuję uruchomić polecenie zarządzania Django z crona. Używam virtualenv, aby utrzymać mój projekt w piaskownicy.

Widziałem przykłady tutaj i gdzie indziej, które pokazują Uruchamianie poleceń zarządzania z poziomu virtualenv takich jak:

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

Jednakże, mimo że syslog pokazuje wpis, kiedy zadanie powinno się rozpocząć, to zadanie nigdy nie zostanie uruchomione (plik dziennika skryptu jest pusty). Jeśli uruchamiam linię ręcznie z powłoki, działa ona zgodnie z oczekiwaniami.

The only way I obecnie można uzyskać polecenie do uruchomienia przez cron, jest rozbicie poleceń i umieścić je w skrypcie dumb Bash wrapper:

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

EDIT:

Ars wymyślił kombinację komend:

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

Przynajmniej w moim przypadku wywołanie skryptu activate dla virtualenv nic nie dało. To działa, tak dalej z programem.

Author: Francisco Couzo, 2010-07-20

7 answers

Powinieneś być w stanie to zrobić używając python w swoim wirtualnym środowisku:

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

EDIT: jeśli twój projekt django nie znajduje się w PYTHONPATH, musisz przełączyć się na właściwy katalog:

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

Możesz również spróbować zalogować błąd z cron:

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

Kolejną rzeczą do spróbowania jest dokonanie tej samej zmiany w skrypcie manage.py na samej górze:

#!/home/my/virtual/bin/python
 188
Author: ars,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-09 22:27:32

Uruchomienie source z pliku cron nie będzie działać, ponieważ cron używa /bin/sh jako domyślnej powłoki, która nie obsługuje source. Musisz ustawić zmienną środowiskową powłoki na /bin/bash:

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

Trudno jest zauważyć, dlaczego to się nie powiedzie, ponieważ /var/log/syslog nie rejestruje szczegółów błędu. Najlepiej alias siebie do root więc otrzymasz e-mail z wszelkich błędów cron. Po prostu dodaj siebie do /etc/aliases i uruchom sendmail -bi.

Więcej informacji proszę.: http://codeinthehole.com/archives/43-Running-django-cronjobs-within-a-virtualenv.html

 73
Author: DavidWinterbottom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-11 19:33:35

Zamiast wygłupiać się wirtualnymi shebangami, po prostu prześlij PATH na crontab.

Z aktywowanego virtualenv, Uruchom te trzy polecenia i skrypty Pythona powinny po prostu działać:

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

Pierwsza linia crontab powinna teraz wyglądać tak:

PATH=/home/me/virtualenv/bin:/usr/bin:/bin:  # [etc...]
 11
Author: joemaller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-12 04:42:01

Jedynym prawidłowym sposobem uruchamiania zadań cron Pythona podczas korzystania z virtualenv jest aktywacja środowiska, a następnie wykonanie środowiska python, aby uruchomić kod.

Jednym ze sposobów na to jest użycie virtualenv activate_this w skrypcie Pythona, zobacz: http://virtualenv.readthedocs.org/en/latest/userguide.html#using-virtualenv-without-bin-python

Innym rozwiązaniem jest wysłanie pełnego polecenia, włączając w to aktywację środowiska i przekierowanie go do /bin/bash. Rozważ to dla Twoje /etc/crontab:

***** root echo 'source /env/bin/activate; python /your/script' | /bin/bash
 8
Author: Ivanhoe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-27 23:34:44

Nie szukaj dalej:

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

Podejście ogólne:

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

Piękno polega na tym, że nie musisz zmieniać zmiennej SHELL dla crontab z sh na bash

 3
Author: Basil Musa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-27 21:32:19

Najlepszym rozwiązaniem było dla mnie zarówno

  • użyj binarnego Pythona w katalogu venv bin /
  • Ustaw ścieżkę Pythona dołączenie katalogu modułów venv.

man python wspomina o modyfikowaniu ścieżki w powłoce w $PYTHONPATH lub w Pythonie za pomocą sys.path

Inne odpowiedzi wspominają o pomysłach na zrobienie tego przy użyciu powłoki. Od Pythona, dodanie następujących linii do mojego skryptu pozwala mi z powodzeniem uruchomić go bezpośrednio z cron.

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

Oto Jak to wygląda w sesja interaktywna --

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
Author: here,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-25 08:00:09

Chciałbym to dodać, ponieważ spędziłem trochę czasu na rozwiązywaniu problemu i nie znalazłem tutaj odpowiedzi na użycie kombinacji zmiennych w cron i virtualenv. Może to komuś pomoże.

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

Nie działał dobrze, gdy był skonfigurowany tak jak

DIR_SMTH= " cd / smth &&. venv / bin/activate "

Thanks @ davidwinterbottom, @reed-sandberg i @ mkb za wskazanie właściwego kierunku. Zaakceptowana odpowiedź faktycznie działa dobrze dopóki twój python musi uruchomić skrypt, który musi uruchomić inny Python binarny z katalogu venv / bin.

 0
Author: Dmitriy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-08 15:26:50