Python Cron 和 virtualenv

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3287038/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 09:25:55  来源:igfitidea点击:

Cron and virtualenv

pythondjangocronvirtualenv

提问by John-Scott

I am trying to run a Django management command from cron. I am using virtualenv to keep my project sandboxed.

我正在尝试从 cron 运行 Django 管理命令。我正在使用 virtualenv 来保持我的项目沙盒化。

I have seen examples here and elsewhere that show running management commands from within virtualenv's like:

我在这里和其他地方看到过一些示例,它们显示了从 virtualenv 中运行管理命令,例如:

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

However, even though syslog shows an entry when the task should have started, this task never actually runs (the log file for the script is empty). If I run the line manually from the shell, it works as expected.

然而,即使 syslog 在任务应该开始时显示了一个条目,这个任务实际上从未运行过(脚本的日志文件是空的)。如果我从 shell 手动运行该行,它会按预期工作。

The only way I can currently get the command to run via cron, is to break the commands up and put them in a dumb bash wrapper script:

我目前可以通过 cron 运行命令的唯一方法是将命令分解并将它们放在一个愚蠢的 bash 包装器脚本中:

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

EDIT:

编辑:

ars came up with a working combination of commands:

ars 提出了一个有效的命令组合:

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

At least in my case, invoking the activate script for the virtualenv did nothing. This works, so on with the show.

至少在我的情况下,为 virtualenv 调用激活脚本什么也没做。这是有效的,以此类推。

采纳答案by ars

You should be able to do this by using the pythonin your virtual environment:

您应该能够通过python在您的虚拟环境中使用 来做到这一点:

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

EDIT: If your django project isn't in the PYTHONPATH, then you'll need to switch to the right directory:

编辑:如果您的 django 项目不在 PYTHONPATH 中,那么您需要切换到正确的目录:

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

You can also try to log the failure from cron:

您还可以尝试从 cron 记录失败:

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

Another thing to try is to make the same change in your manage.pyscript at the very top:

要尝试的另一件事是manage.py在最顶部的脚本中进行相同的更改:

#!/home/my/virtual/bin/python

回答by DavidWinterbottom

Running sourcefrom a cronfile won't work as cron uses /bin/shas its default shell, which doesn't support source. You need to set the SHELL environment variable to be /bin/bash:

source从 cronfile运行将无法正常工作,因为 cron/bin/sh用作其默认 shell,它不支持source. 您需要将 SHELL 环境变量设置为/bin/bash

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

It's tricky to spot why this fails as /var/log/syslogdoesn't log the error details. Best to alias yourself to root so you get emailed with any cron errors. Simply add yourself to /etc/aliasesand run sendmail -bi.

由于/var/log/syslog没有记录错误详细信息,因此很难发现为什么会失败。最好将自己的别名设置为 root,以便您通过电子邮件收到任何 cron 错误。只需将自己添加到/etc/aliases并运行sendmail -bi.

More info here: http://codeinthehole.com/archives/43-Running-django-cronjobs-within-a-virtualenv.html

更多信息:http: //codeinthehole.com/archives/43-Running-django-cronjobs-within-a-virtualenv.html

the link above is changed to: https://codeinthehole.com/tips/running-django-cronjobs-within-a-virtualenv/

上面的链接改为:https: //codeinthehole.com/tips/running-django-cronjobs-within-a-virtualenv/

回答by joemaller

Rather than mucking around with virtualenv-specific shebangs, just prepend PATHonto the crontab.

而不是与 virtualenv 特定的 shebangs 混在一起,只需添加PATH到 crontab 上即可。

From an activated virtualenv, run these three commands and python scripts should just work:

从激活的 virtualenv 运行这三个命令,python 脚本应该可以正常工作:

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

The crontab's first line should now look like this:

crontab 的第一行现在应该是这样的:

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

回答by Ivanhoe

The only correct way to run python cron jobs when using a virtualenv is to activate the environment and then execute the environment's python to run your code.

使用 virtualenv 时运行 python cron 作业的唯一正确方法是激活环境,然后执行环境的 python 来运行您的代码。

One way to do this is use virtualenv's activate_thisin your python script, see: http://virtualenv.readthedocs.org/en/latest/userguide.html#using-virtualenv-without-bin-python

一种方法是activate_this在您的 python 脚本中使用 virtualenv ,请参阅:http: //virtualenv.readthedocs.org/en/latest/userguide.html#using-virtualenv-without-bin-python

Another solution is echoing the complete command including activating the environment and piping it into /bin/bash. Consider this for your /etc/crontab:

另一种解决方案是回显完整的命令,包括激活环境并将其通过管道传输到/bin/bash. 为您考虑这一点/etc/crontab

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

回答by here

The best solution for me was to both

对我来说最好的解决方案是两者

  • use the python binary in the venv bin/ directory
  • set the python path to include the venv modules directory.
  • 使用 venv bin/ 目录中的 python 二进制文件
  • 设置 python 路径以包含 venv 模块目录。

man pythonmentions modifying the path in shell at $PYTHONPATHor in python with sys.path

man python提到修改 shell at$PYTHONPATH或 python 中的路径sys.path

Other answers mention ideas for doing this using the shell. From python, adding the following lines to my script allows me to successfully run it directly from cron.

其他答案提到了使用 shell 执行此操作的想法。在 python 中,将以下几行添加到我的脚本中可以让我直接从 cron 成功运行它。

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

Here's how it looks in an interactive session --

这是它在交互式会话中的样子——

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

回答by Basil Musa

Don't look any further:

不要再看了:

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

Generic approach:

通用方法:

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

The beauty about this is you DO NOT need to change the SHELLvariable for crontab from shto bash

这样做的好处是您不需要将SHELLcrontab的变量从更改shbash

回答by Dmitriy

I'd like to add this because I spent some time solving the issue and did not find an answer here for combination of variables usage in cron and virtualenv. So maybe it'll help someone.

我想添加这个是因为我花了一些时间来解决这个问题,但在这里没有找到有关 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

It did not work well when it was configured like

当它被配置为时它不能很好地工作

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

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

Thanks @davidwinterbottom, @reed-sandbergand @mkbfor giving the right direction. The accepted answer actually works fine until your python need to run a script which have to run another python binary from venv/bin directory.

感谢@davidwinterbottom@reed-sandberg@mkb提供正确的方向。接受的答案实际上工作正常,直到您的 python 需要运行一个脚本,该脚本必须从 venv/bin 目录运行另一个 python 二进制文件。

回答by Arun Thundyill Saseendran

This is a solution that has worked well for me.

这是一个对我来说效果很好的解决方案。

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

I am using miniconda with Conda version 4.7.12 on a Ubuntu 18.04.3 LTS.

我在 Ubuntu 18.04.3 LTS 上使用带有 Conda 版本 4.7.12 的 miniconda。

I am able to place the above inside a script and run it via crontab as well without any trouble.

我能够将上述内容放在脚本中并通过 crontab 运行它,没有任何问题。

回答by Ramesh Ponnusamy

python script

蟒蛇脚本

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 command

定时命令

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

In above command

在上面的命令中

  • */1 * * * *- Execute every one minte
  • cd /Workspace/testcron/- Path of the python script
  • /Workspace/testcron/venvcron/bin/python3- Virtualenv path
  • Workspace/testcron/testcronwithparam.py- File path
  • param- parameter
  • */1 * * * *- 每分钟执行一次
  • cd /Workspace/testcron/- python 脚本的路径
  • /Workspace/testcron/venvcron/bin/python3- Virtualenv 路径
  • Workspace/testcron/testcronwithparam.py- 文件路径
  • param- 参数