Cron和virtualenv

Joh*_*ott 210 python django cron virtualenv

我试图从cron运行Django管理命令.我正在使用virtualenv来保持我的项目沙箱.

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

0 3 * * * source /home/user/project/env/bin/activate && /home/user/project/manage.py command arg
Run Code Online (Sandbox Code Playgroud)

但是,即使syslog在任务应该启动时显示一个条目,该任务也从未实际运行(脚本的日志文件为空).如果我从shell手动运行该行,它将按预期工作.

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

#!/bin/sh
source /home/user/project/env/bin/activate
cd /home/user/project/
./manage.py command arg
Run Code Online (Sandbox Code Playgroud)

编辑:

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

0 3 * * * cd /home/user/project && /home/user/project/env/bin/python /home/user/project/manage.py command arg
Run Code Online (Sandbox Code Playgroud)

至少在我的情况下,调用virtualenv的激活脚本什么也没做.这个有用,等等.

ars*_*ars 231

您应该可以通过python在虚拟环境中使用它来执行此操作:

/home/my/virtual/bin/python /home/my/project/manage.py command arg
Run Code Online (Sandbox Code Playgroud)

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

cd /home/my/project && /home/my/virtual/bin/python ...
Run Code Online (Sandbox Code Playgroud)

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

cd /home/my/project && /home/my/virtual/bin/python /home/my/project/manage.py > /tmp/cronlog.txt 2>&1
Run Code Online (Sandbox Code Playgroud)

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

#!/home/my/virtual/bin/python
Run Code Online (Sandbox Code Playgroud)

  • 测试的一个好方法是执行/ bin/sh,然后尝试从那里执行命令.至少你将拥有与cron相同的环境设置. (6认同)
  • 那也是行不通的。忘记把它列入我的不起作用的事情清单中。是的,我可以在 shell 中手动运行该命令,但它在 cron 中不起作用。 (3认同)

Dav*_*tom 89

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
Run Code Online (Sandbox Code Playgroud)

由于/var/log/syslog没有记录错误细节,因此发现失败的原因很棘手.最好将自己别名为root,以便通过电子邮件发送任何cron错误.只需添加自己/etc/aliases并运行sendmail -bi.

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

  • 要么 '.' (点命令),由/ bin/sh`支持./路径/到/的virtualenv /斌/ activate` (11认同)
  • DavidWinterbottom,如果这是你的真名,你就是我的英雄.我从来不知道关于sh vs bash和源文件.你已经为我的小bash脚本世界的家伙发光了.谢谢. (4认同)
  • 什么是“根”?谁能解释一下 (2认同)

dav*_*xxx 41

我对第 n 个答案感到抱歉,但我检查了答案,发现确实更简单、更整洁。

\n

长话短说

\n

在 cron 中使用 venv 的 python 二进制文件:

\n
0 3 * * * /home/user/project/env/bin/python /home/user/project/manage.py \n
Run Code Online (Sandbox Code Playgroud)\n

很长的故事

\n

当我们想要使用特定虚拟环境(即二进制文件和模块)的 python 配置设置当前 shell 时,我们激活虚拟环境。
\n与当前 shell 相关:在当前 shell 上执行多个 python 命令,而不需要引用 venv 的完整 python 路径。
\n在 cron 甚至 bash 的框架中,激活环境的值是什么?\n除了我在一些答案中读到的一些引用,而bash不是sh或仍然定义一个包装器来调用 Python 代码。但我们到底为什么要为这些烦恼呢?

\n

我重复一遍,就这样做:

\n
0 3 * * * /home/user/project/env/bin/python /home/user/project/manage.py \n
Run Code Online (Sandbox Code Playgroud)\n

文件确认:

\n
\n

您不需要\xe2\x80\x99t特别需要激活环境;激活\n只需将虚拟环境\xe2\x80\x99s 二进制目录添加到您的路径中,\n以便 \xe2\x80\x9cpython\xe2\x80\x9d 调用虚拟环境\xe2\x80\x99s Python 解释器\n并且您可以运行已安装的脚本,而无需使用其完整\n路径。但是,安装在虚拟环境中的所有脚本都应该可以在不激活的情况下运行,并自动使用虚拟环境 xe2x80x99s Python 运行。

\n
\n

  • 似乎人们永远不会介意学习他们所使用的技术的文档!感谢您让正派仍然存在于这个星球! (6认同)

Bas*_*usa 11

不要再看了:

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
Run Code Online (Sandbox Code Playgroud)

通用方法:

* * * * * /usr/bin/env bash -c 'YOUR_COMMAND_HERE' > /dev/null 2>&1
Run Code Online (Sandbox Code Playgroud)

关于这一点的美妙之处在于您不需要将SHELLcrontab 的变量更改shbash

  • “别再往前看了”是一句大胆的话。特别是,当以下答案声称知道“唯一正确的方法”时:/sf/answers/1590723991/ (3认同)

joe*_*ler 10

而不是使用virtualenv特定的shebangs,只是PATH在crontab上.

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

$ echo "PATH=$PATH" > myserver.cron
$ crontab -l >> myserver.cron
$ crontab myserver.cron
Run Code Online (Sandbox Code Playgroud)

crontab的第一行现在看起来像这样:

PATH=/home/me/virtualenv/bin:/usr/bin:/bin:  # [etc...]
Run Code Online (Sandbox Code Playgroud)

  • 不是一个好的解决方案 然后,crontab中的每个python任务都将使用virtualenv中的二进制文件运行.使该二进制文件成为_pseudo-global_ python违背了virtualenv的目的. (11认同)

小智 10

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

一种方法是activate_this在你的python脚本中使用virtualenv ,参见: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
Run Code Online (Sandbox Code Playgroud)

  • 这不是"唯一正确的方法".我只是通过将cronjob指向virtualenv的python二进制文件,例如'/ home/user/folder/env/bin/python',成功地在virtualenv中执行了一个脚本.无需激活任何环境. (4认同)
  • 我很好奇是否有共识认为这实际上是唯一正确的方法。 (2认同)
  • 这可能是唯一正确的方法。但还有其他有效的方法。 (2认同)
  • 您不需要将命令通过管道传输到 bash。只需使用“.”命令而不是“source”即可。请参阅/sf/ask/230092691/#69037846 (2认同)

wis*_*cky 6

这是一种简单的方法,可以使 crontab 命令与常规命令非常相似(在 Ubuntu 18.04 中测试)。需要记住的一些要点:

  • 您可以使用该.命令代替source. (crontabsh默认使用,而不是bash,所以它没有source。)
  • ~$variables在 crontab 命令中展开。(只有 crontab 环境语句不进行变量扩展。)

如果您有文件,以下是示例~/myproject/main.py

* * * * * cd ~/myproject && . .venv/bin/activate && python main.py > /tmp/out1 2>&1
Run Code Online (Sandbox Code Playgroud)

你也可以直接调用venv目录下的具体路径python,那么就不需要调用activate.

* * * * * ~/myproject/.venv/bin/python ~/myproject/main.py > /tmp/out2 2>&1
Run Code Online (Sandbox Code Playgroud)

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

* * * * * project_dir=~/myproject ; $project_dir/.venv/bin/python $project_dir/main.py > /tmp/out3 2>&1
Run Code Online (Sandbox Code Playgroud)


her*_*ere 5

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

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

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

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

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

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

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
>>>
Run Code Online (Sandbox Code Playgroud)


Dmi*_*riy 5

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

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

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

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