首页 文章

Cron和virtualenv

提问于
浏览
183

我试图从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的激活脚本什么也没做 . 这个有用,等等 .

7 回答

  • 8

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

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

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

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

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

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

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

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

    从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

  • 0

    而不是使用virtualenv特定的shebangs,只需将 PATH 添加到crontab上 .

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

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

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

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

    使用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
    
  • 75

    不要再看了:

    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
    

    通用方法:

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

    关于这一点的美妙之处在于您无需将crontab的 SHELL 变量从 sh 更改为 bash

  • 4

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

    • 在venv bin /目录中使用python二进制文件

    • 设置python路径以包含venv模块目录 .

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

    其他答案提到使用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
    >>>
    
  • 11

    我想补充一点,因为我花了一些时间来解决这个问题,并且在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
    

    它配置完毕后效果不佳

    DIR_SMTH =“cd / smth && . venv / bin / activate”

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

相关问题