我正在尝试从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的激活脚本没有任何作用。这招管用,所以节目继续。


当前回答

从cronfile运行source将不起作用,因为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

很难发现为什么会失败,因为/var/log/syslog没有记录错误细节。最好将自己别名为root,这样你就会收到带有任何cron错误的电子邮件。只需将自己添加到/etc/aliases并运行sendmail -bi。

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

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

其他回答

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

由于cron在它自己的最小sh环境中执行,下面是我在虚拟环境中运行Python脚本的方法:

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

(注:如果。~ /。Bash_profile不适合您,那么请尝试一下。~ /。Bashrc或。~ /。配置文件取决于您的服务器如何设置。)

这将加载您的bash shell环境,然后激活您的Python虚拟环境,基本上为您留下与测试脚本相同的设置。

不需要在crontab中定义环境变量,也不需要修改现有脚本。

这是一种保持crontab命令与常规命令非常相似的简单方法(在Ubuntu 18.04中进行了测试)。一些需要记住的关键注意事项:

你可以使用。命令,而不是源。(crontab默认使用sh,而不是bash,因此它没有source。) ~和$变量在crontab命令中展开。(只有crontab环境语句不进行变量展开。)

这里有一些例子,如果你有一个文件~/myproject/main.py:

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

您也可以直接调用venv目录中python的特定路径,然后不需要调用activate。

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

这样做的缺点是您需要指定两次项目路径,这使得维护更加棘手。为了避免这种情况,你可以使用一个shell变量,这样你只指定一次项目路径:

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

这是一个对我很有效的解决办法。

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

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

我可以把上面的代码放在一个脚本中,并通过crontab运行它,没有任何麻烦。

在venv中添加Python安装路径,但不要激活环境。

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

就是这么简单。