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
Cron and virtualenv
提问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的变量从更改sh为bash
回答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- 参数

