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 ничего не сделал. Это работает, так и с шоу.

20 ответов

Решение

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

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

РЕДАКТИРОВАТЬ: Если ваш проект 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, Вам необходимо установить переменную среды 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

Прошу прощения за этот n-й ответ, но я проверил ответы, и они действительно попроще и аккуратнее.

Короче

Используйте двоичный файл python вашего venv в своем cron:


Длинная история

Мы активируем виртуальную среду, когда хотим установить текущую оболочку с конфигурацией python для этой конкретной виртуальной среды (то есть двоичных файлов и ее модулей).
Важно работать с текущей оболочкой: выполнять несколько команд python в текущей оболочке без необходимости ссылаться на полный путь python к venv.
Какое значение активировать среду в кадре cron или даже bash? Кроме того, в некоторых ответах я читал ссылки на bash скорее, чем shили еще определить оболочку для вызова кода Python. Но какого черта мы должны с этим возиться?

Повторяю, просто сделай это:

      0 3 * * * /home/user/project/env/bin/python /home/user/project/manage.py 

В документации подтверждает , что:

Вам не нужно специально активировать среду; активация просто добавляет двоичный каталог виртуальной среды к вашему пути, так что «python» вызывает интерпретатор Python виртуальной среды, и вы можете запускать установленные сценарии без необходимости использовать их полный путь. Однако все сценарии, установленные в виртуальной среде, должны запускаться без ее активации и автоматически запускаться с Python виртуальной среды.

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

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

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

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

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

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

Вместо того, чтобы дурачиться с помощью виртуозных шебангов, просто приготовьте 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...]

Это простой способ сохранить команду crontab очень похожей на обычную команду (проверено в Ubuntu 18.04). Некоторые важные примечания, о которых следует помнить:

  • Вы можете использовать .команда вместо. (crontab использует sh по умолчанию не bash, поэтому у него нет source.)
  • ~ а также $variablesраскрываются в командах crontab. (Только операторы среды crontab не расширяют переменные.)

Вот примеры, если у вас есть файл ~/myproject/main.py:

      * * * * * cd ~/myproject && . .venv/bin/activate && python main.py > /tmp/out1 2>&1

Вы также можете напрямую вызвать конкретный путь к python в каталоге venv, то звонить не нужно activate.

      * * * * * ~/myproject/.venv/bin/python ~/myproject/main.py > /tmp/out2 2>&1

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

      * * * * * project_dir=~/myproject ; $project_dir/.venv/bin/python $project_dir/main.py > /tmp/out3 2>&1

Я хотел бы добавить это, потому что я потратил некоторое время на решение проблемы и не нашел здесь ответа на вопрос об использовании комбинации переменных в 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.

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

  • используйте двоичный файл python в каталоге venv bin/
  • установите путь к Python, чтобы включить каталог модулей 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
>>>

Если вы используете python и используете виртуальную среду Conda, где ваш сценарий python содержит python shebang #! / Usr/bin/env, работает следующее:

* * * * * cd /home/user/project && /home/user/anaconda3/envs/envname/bin/python script.py 2>&1

Кроме того, если вы хотите зафиксировать какие-либо выходные данные в вашем скрипте (например, печать, ошибки и т. Д.), Вы можете использовать следующее:

* * * * * cd /home/user/project && /home/user/anaconda3/envs/envname/bin/python script.py >> /home/user/folder/script_name.log 2>&1

Добавьте путь установки Python в venv, но не активируйте среду.

      * * * * * /HDD1/shritam_kumar/VENOM/venv/bin/python /HDD1/shritam_kumar/Projects/Voelkner-DE/schedule_product_BA.py

Это так просто.

скрипт Python

from datetime import datetime                                                                                                                                                                
import boto   # check wheather its taking the virtualenv or not                                                                                                                                                                        
import sys                                                                                                                                                                                   
param1=sys.argv[1]     #Param                                                                                                                                                                                                                                                                                                                                                                    
myFile = open('appendtxt.txt', 'a')                                                                                                                                                      
myFile.write('\nAccessed on ' + param1+str(datetime.now())) 

Команда cron

 */1 * * * *  cd /Workspace/testcron/ && /Workspace/testcron/venvcron/bin/python3  /Workspace/testcron/testcronwithparam.py param  

В приведенной выше команде

  • * / 1 * * * * - Выполнять каждую минуту
  • cd /Workspace/testcron/ - Путь к скрипту python
  • /Workspace/testcron/ venvcron / bin / python3 - путь к Virtualenv
  • Workspace / testcron / testcronwithparam.py - Путь к файлу
  • param - параметр

У меня была такая же проблема, и я потратил много времени на ее решение. Ни одно из решений здесь не помогло мне, поэтому я делюсь тем, что сработало для меня:

  1. Откройте новый файл "pick_name.sh", откройте его в каталоге вашего проекта.
  2. Внутри файла «pick_name.sh» напишите и сохраните следующие строки:
      #!/bin/bash
source /YOUR_VIRTUAL_ENV_PATH/bin/activate
export PYTHONPATH="${PYTHONPATH}:/PATH_TO_CUSTOM_MODULE_YOU_CREATED**OPTIONAL**"
export PYTHONPATH="${PYTHONPATH}:/PATH_TO_ANOTHER_CUSTOM_MODULE_YOU_CREATED**OPTIONAL**"
cd /PATH_TO_DIR_STORING_FILE_NAME.PY
python file_name.py
  1. Перейдите в /var/spool/cron/crontabs (или туда, где находится ваш файл управления cron) и откройте «корневой» файл.
  2. Добавьте эти строки в корневой файл, который находится в папке crontab:
      # m h  dom mon dow   command
* * * * * /PATH_TO_DIR_WHERE_PICK_NAME.SH_SITS/pick_name.sh >> /YOUR_PROJECT_DIR/cron_output.txt 2>&1

Примечания:

  • Эта команда (раздел 4.) запустит файл "pick_name.sh". В этом примере он запускается каждую минуту, поэтому убедитесь, что вы изменили его в соответствии с вашими потребностями. Он записывает все журналы в файл журнала с именем «cron_ouput». Не нужно создавать файл заранее, он будет создан автоматически.
  • Обязательно замените все пути (я написал их заглавными буквами) на ваши пути.
  • Вы можете изменить имена файлов, если это так, обязательно измените их во всех проявлениях в моих инструкциях, чтобы избежать ошибок.
  • Если вы хотите добавить еще один py-файл для запуска с помощью cron, вам нужно добавить его в файл «pick_nam.sh» *, а не в cron. Просто продублируйте строки раздела 2. в "pick_nam.sh", но без части "#!/bin/bash". Затем каждый раз, когда cron будет запускать «pick_name.sh», он будет запускать все файлы, которые вы указали внутри него.
  • Обязательно перезапустите cron после изменений, это могло бы сэкономить мне много времени на отладку, используйте эту команду:
      systemctl restart cron

Я добавил следующий сценарий, как в моем проекте Django, он отправляет virtualenv, а затем запускает manage.pyскрипт с любыми аргументами, которые вы ему передадите. В целом это позволяет очень легко запускать команды внутри virtualenv (cron, systemd, в основном где угодно):

      #! /bin/bash

# this is a convenience script that first sources the venv (assumed to be in
# ../venv) and then executes manage.py with whatever arguments you supply the
# script with. this is useful if you need to execute the manage.py from
# somewhere where the venv isn't sourced (e.g. system scripts)

# get the script's location
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"

# source venv <- UPDATE THE PATH HERE WITH YOUR VENV's PATH
source $DIR/../venv/bin/activate

# run manage.py script
$DIR/manage.py "$@"

Затем в записи cron вы можете просто запустить:

      0 3 * * * /home/user/project/manage.sh command arg

Просто помните, что вам нужно сделать manage.sh исполняемый файл сценария

Поскольку cron выполняет свои собственные минимальные sh среды, вот что я делаю для запуска скриптов Python в виртуальной среде:

      * * * * * . ~/.bash_profile; . ~/path/to/venv/bin/activate; python ~/path/to/script.py

(Примечание: если . ~/.bash_profile не работает для вас, тогда попробуйте . ~/.bashrc или же . ~/.profile в зависимости от того, как настроен ваш сервер.)

Это загружает ваш bash shell, затем активирует вашу виртуальную среду Python, по сути оставляя вас с той же настройкой, в которой вы тестировали свои скрипты.

Нет необходимости определять переменные среды в crontab и изменять существующие сценарии.

Я обнаружил, что это сработало для меня (общее):

      * * * * * cd /home/user/project && /home/user/project/.venv/bin/python /home/user/project/project.py  >> /home/user/project/project.log 2>&1

Примечание:

  • создает файл журнала project.log в каталоге проекта (устранение неполадок)

  • предполагает, что .venv уже создан

  • предполагает, что эти записи также присутствуют в файле crontab:

    SHELL=/bin/bashPATH=/sbin:/bin:/usr/sbin:/usr/bin

Если вы, как и я, пользователь MacOS, вы можете проверить сообщение об ошибке crontab в файле /var/mail/{username}. так

      tail /var/mail/{username}

Если есть ошибка «Операция не разрешена», возможно, вам нужно добавить cron в приложения полного доступа к диску (Безопасность и конфиденциальность> Конфиденциальность> Приложения/исполнители полного доступа к диску).

И нажмите кнопку +, перейдите в /usr/sbin, дважды щелкните файл cron . тогда он исправит ошибку «не разрешено». подробные шаги

И это мой код:

      0 19 * * * cd /Users/user/Desktop/Project && source /Users/user/Desktop/Project/venv/bin/activate && python command arg

Это решение, которое мне понравилось.

source /root/miniconda3/etc/profile.d/conda.sh && \
conda activate <your_env> && \
python <your_application> &

Я использую miniconda с Conda версии 4.7.12 на Ubuntu 18.04.3 LTS.

Я могу поместить это в скрипт и запустить его через crontab без каких-либо проблем.

У меня была такая же проблема:

Я написал специальную команду django для проверки координат положения geodjango внутри полигонов geodjango, и у меня возникли проблемы с автоматизацией выполнения задачи, однако использование этой команды с crontab сработало для меня:

      * * * * * ./home/project/locations/locations.sh >> /var/log/locations.log 2>&1

Это также будет работать с crontab -e

      * */5 * * * cd /home/project && sudo /home/project/venv/bin/python scripte.py
Другие вопросы по тегам