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 - параметр
У меня была такая же проблема, и я потратил много времени на ее решение. Ни одно из решений здесь не помогло мне, поэтому я делюсь тем, что сработало для меня:
- Откройте новый файл "pick_name.sh", откройте его в каталоге вашего проекта.
- Внутри файла «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
- Перейдите в /var/spool/cron/crontabs (или туда, где находится ваш файл управления cron) и откройте «корневой» файл.
- Добавьте эти строки в корневой файл, который находится в папке 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