如何检测Heroku的环境?

时间:2012-02-21 18:58:07

标签: python django deployment heroku environment

我有一个Django webapp,我想检查它是否在Heroku堆栈上运行(有条件启用调试等)有没有简单的方法可以做到这一点?环境变量,也许?

我知道我也可以反过来这样做 - 也就是说,让它检测它是否在开发者机器上运行,但这听起来并不合适。

7 个答案:

答案 0 :(得分:21)

ENV var似乎是最明显的做法。要么找到你知道存在的ENV var,要么设置你自己的:

on_heroku = False
if 'YOUR_ENV_VAR' in os.environ:
  on_heroku = True

更多信息:http://devcenter.heroku.com/articles/config-vars

答案 1 :(得分:17)

与Neil建议的相似,我会做以下事情:

debug = True
if 'SOME_ENV_VAR' in os.environ:
    debug = False

我看到有些人使用if 'PORT' in os.environ:但不幸的是,当你在本地运行foreman start时PORT变量存在,所以没有办法区分本地测试与工头和部署在Heroku上。

我还建议使用其中一个env变种:

  1. Heroku开箱即用(而不是设置和检查自己的)
  2. 不太可能在您的本地环境中找到
  3. 在发布之日,Heroku有以下环境变量:

    ['PATH', 'PS1', 'COLUMNS', 'TERM', 'PORT', 'LINES', 'LANG', 'SHLVL', 'LIBRARY_PATH', 'PWD', 'LD_LIBRARY_PATH', 'PYTHONPATH', 'DYNO', 'PYTHONHASHSEED', 'PYTHONUNBUFFERED', 'PYTHONHOME', 'HOME', '_']

    我通常选择if 'DYNO' in os.environ:,因为它似乎是最具特异性的Heroku(还有谁会使用dyno这个词,对吧?)。

    而且我也喜欢将其格式化为if-else语句,因为它更明确:

    if 'DYNO' in os.environ:
        debug = False
    else:
        debug = True
    

答案 2 :(得分:11)

首先在heroku上设置环境变量ON_HEROKU

$ heroku config:set ON_HEROKU=1

然后在settings.py

import os

# define if on heroku environment
ON_HEROKU = 'ON_HEROKU' in os.environ

答案 3 :(得分:1)

最可靠的方法是设置如上所述的环境变量。 如果这不可能,那么你可以在文件系统中找到一些标志,但它们可能不是/不是万无一失

  • Heroku实例都有路径/app - 正在运行的文件和脚本也将在此下,因此您可以检查目录的存在和/或脚本是否正在运行从它下面。

  • 有一个空目录/etc/heroku

  • /etc/hosts可能会添加一些与heroku相关的域名 ~ $ cat /etc/hosts <snip>.dyno.rt.heroku.com

任何这些都可以随时改变

您的milage可能会有所不同

答案 4 :(得分:0)

在此处详细了解:https://devcenter.heroku.com/articles/config-vars

我的解决方案:

$ heroku config:set HEROKU=1

这些环境变量是持久性的 - 它们将在部署和应用程序重新启动时保持不变 - 因此,除非您需要更改值,否则只需设置一次。

然后你可以在你的应用中测试它的存在。:

>>> 'HEROKU' in os.environ
True

答案 5 :(得分:-1)

简短版本:检查时区是否为UTC / GMT:

if not 'ORIGINAL_TIMEZONE' in os.environ:
    f = os.popen('date +%Z')
    tz = f.read().upper()
    os.environ['ORIGINAL_TIMEZONE']=tz


tz = os.environ['ORIGINAL_TIMEZONE']
if tz != '' and (not 'utc' in tz.lower()) and (not 'gmt' in tz.lower()):
    print 'Definitely not running on Heroku (or in production in general)'
else:
    print 'Assume that we are running on Heroku (or in production in general)'

这比if tz=='UTC\n'更保守:如果有疑问,假设我们正在生产中。请注意,我们将时区保存到环境变量,因为settings.py可能会多次执行。实际上,开发服务器执行它两次,第二次系统时区已经“UTC&#39; (或settings.TIMEZONE中的任何内容)。

长版:

确保我们永远不会使用DEBUG=True在Heroku上运行,并且即使使用DEBUG=False,我们也永远不会在Heroku上运行开发服务器。来自settings.py

RUNNING_DEV_SERVER = (len(sys.argv) > 1) and (sys.argv[1] == 'runserver')

DEBUG = RUNNING_DEV_SERVER

TEMPLATE_DEBUG = DEBUG

# Detect the timezone
if not 'ORIGINAL_TIMEZONE' in os.environ:
    f = os.popen('date +%Z')
    tz = f.read().upper()
    os.environ['ORIGINAL_TIMEZONE']=tz
    print ('DEBUG: %d, RUNNING_DEV_SERVER: %d, system timezone: %s ' % (DEBUG, RUNNING_DEV_SERVER, tz))


if not (DEBUG or RUNNING_DEV_SERVER):
    SECRET_KEY = os.environ['SECRET_KEY']
else:
    print 'Running in DEBUG MODE! Hope this is not in production!'

    SECRET_KEY = 'DEBUG_INSECURE_SECRET_KEY_ae$kh(7b%$+a fcw_bdnzl#)$t88x7h2-p%eg_ei5m=w&2p-)1+'

    # But what if we are idiots and are still somehow running with DEBUG=True in production?!
    # 1. Make sure SECRET_KEY is not set
    assert not SECRET_KEY in os.environ
    # 2. Make sure the timezone is not UTC or GMT (indicating production)

    tz = os.environ['ORIGINAL_TIMEZONE']
    assert tz != '' and (not 'UTC' in tz) and (not 'GMT' in tz)

    # 3. Look for environment variables suggesting we are in PROD
    for key in os.environ:
        for red_flag in ['heroku', 'amazon', 'aws', 'prod', 'gondor']:
            assert not red_flag in key.lower()
            assert not red_flag in os.environ[key].lower()

如果你真的想在Heroku上运行开发服务器,我建议你添加一个环境变量来指定你可以做到的日期。然后只有今天这个日期才会继续。这样您就可以在开始开发工作之前更改此变量,但如果您忘记取消它,第二天您仍然可以防止在生产中意外运行它。当然,如果你想要超级保守,你也可以在例外情况下指定1小时的窗口。

最后,如果你决定采用上面建议的方法,那么当你使用它时,也要安装django-security,将djangosecurity添加到INSTALLED_APPS,然后添加到{{1}的末尾}}:

settings.py

答案 6 :(得分:-1)

DATABASE_URL环境变量

in_heroku = False
if 'DATABASE_URL' in os.environ:
    in_heroku = True

我认为您需要为您的应用启用数据库:

heroku addons:create heroku-postgresql:hobby-dev

但它是免费的,而且很可能是你要做的。

Heroku在运行其应用程序时使此环境变量可用,特别是用作:

import dj_database_url
if in_heroku:
    DATABASES = {'default': dj_database_url.config()}
else:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }

不是万无一失的,因为该变量可能在本地定义,但对于简单的情况很方便。

heroku run env

也可能会显示其他可能的变量,如:

  • DYNO_RAM
  • WEB_CONCURRENCY

但我不确定这些是否记录为DATABASE_URL