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

我在这里和其他地方看到了从virtualenv中运行管理命令的示例,例如:

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

然而,尽管syslog显示了任务应该在何时启动的条目,但该任务从未实际运行(脚本的日志文件为空)。如果我从shell中手动运行这一行,它将按预期工作。

我目前可以通过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的激活脚本没有任何作用。这招管用,所以节目继续。


当前回答

对我来说,最好的解决办法是两者兼得

使用venv bin/目录下的python二进制文件 设置python路径 要包含venv模块目录。

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

其他回答提到了使用shell来实现这一点的想法。从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脚本包含shebang #!/usr/bin/env python:

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

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

当它被配置成

生下来的微片venv / bin / sh activate。”

感谢@davidwinterbottom, @reed-sandberg和@mkb给出了正确的方向。接受的答案实际上工作得很好,直到你的python需要运行一个脚本,必须从venv/bin目录运行另一个python二进制文件。

我也有同样的问题:

我写了一个自定义的django命令来检查geodjango多边形内部的geodjango位置坐标,并且在自动化任务运行时遇到了麻烦,然而使用crontab这个命令对我来说是有效的:

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

对我来说,最好的解决办法是两者兼得

使用venv bin/目录下的python二进制文件 设置python路径 要包含venv模块目录。

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

其他回答提到了使用shell来实现这一点的想法。从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
>>>

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

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

另一种解决方案是回显完整的命令,包括激活环境并将其管道到/bin/bash.考虑一下你的/etc/crontab:

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