我有一个Django webapp,我想检查它是否在Heroku堆栈上运行(用于有条件地启用调试等)。有什么简单的方法可以做到这一点吗?我知道我可能也可以用另一种方式来做--也就是说,让它检测它是否在开发人员的机器上运行,但这听起来不太对。
zdwk9cvp1#
一个ENV变量似乎是最明显的方法。要么寻找一个你知道存在的ENV变量,要么设置你自己的:
on_heroku = Falseif 'YOUR_ENV_VAR' in os.environ: on_heroku = True
on_heroku = False
if 'YOUR_ENV_VAR' in os.environ:
on_heroku = True
字符串更多信息:http://devcenter.heroku.com/articles/config-vars
i7uq4tfw2#
与尼尔的建议类似,我会做以下事情:
debug = Trueif 'SOME_ENV_VAR' in os.environ: debug = False
debug = True
if 'SOME_ENV_VAR' in os.environ:
debug = False
字符串我见过一些人使用if 'PORT' in os.environ:,但不幸的是,当您在本地运行foreman start时,PORT变量是存在的,所以没有办法区分使用foreman进行的本地测试和在Heroku上进行的部署。我还建议使用一个env变量:
if 'PORT' in os.environ:
foreman start
['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:
if 'DYNO' in os.environ: debug = Falseelse: debug = True
else:
型
bvn4nwqk3#
首先在heroku上设置环境变量ON_HEROKU:
ON_HEROKU
$ heroku config:set ON_HEROKU=1
字符串然后在settings.py中
settings.py
import os# define if on heroku environmentON_HEROKU = 'ON_HEROKU' in os.environ
import os
# define if on heroku environment
ON_HEROKU = 'ON_HEROKU' in os.environ
ssgvzors4#
阅读更多:https://devcenter.heroku.com/articles/config-vars我的解决方案:
$ heroku config:set HEROKU=1
字符串这些环境变量是持久的-它们将在部署和应用重新启动时保持不变-因此除非您需要更改值,否则只需设置一次。然后,您可以在应用程序中测试它的存在。
>>> 'HEROKU' in os.environTrue
>>> 'HEROKU' in os.environ
True
gopyfrb35#
最可靠的方法是如上所述设置一个环境变量。如果这不可能,您可以在文件系统中查找一些迹象,但它们可能不是万无一失的
/app
/etc/heroku
/etc/hosts
~ $ cat /etc/hosts <snip>.dyno.rt.heroku.com
您的里程可能会有所不同
6g8kf2rb6#
DATABASE_URL环境变量
DATABASE_URL
in_heroku = Falseif 'DATABASE_URL' in os.environ: in_heroku = True
in_heroku = False
if 'DATABASE_URL' in os.environ:
in_heroku = True
字符串我认为你需要为你的应用启用数据库:
heroku addons:create heroku-postgresql:hobby-dev
型但它是免费的,而且很可能是你无论如何都要做的。Heroku在运行其应用程序时提供此环境变量,特别是用于以下用途:
import dj_database_urlif in_heroku: DATABASES = {'default': dj_database_url.config()}else: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } }
import dj_database_url
if in_heroku:
DATABASES = {'default': dj_database_url.config()}
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
型并不是万无一失的,因为该变量可能是本地定义的,但对于简单的情况很方便。
heroku run env
型也可以显示其他可能的变量,例如:
DYNO_RAM
WEB_CONCURRENCY
但我不确定这些是否像DATABASE_URL一样被记录下来。
7ajki6be7#
**短版本:**检查时区是否为UTC/GMT:
if not 'ORIGINAL_TIMEZONE' in os.environ: f = os.popen('date +%Z') tz = f.read().upper() os.environ['ORIGINAL_TIMEZONE']=tztz = 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 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)'
print 'Assume that we are running on Heroku (or in production in general)'
字符串这比if tz=='UTC\n'更保守:如果有疑问,假设我们在生产环境中。请注意,我们将时区保存到环境变量中,因为settings.py可能会执行多次。实际上,开发服务器执行了两次,第二次系统时区已经是'UTC'(或settings.TIMEZONE中的任何内容)。
if tz=='UTC\n'
settings.TIMEZONE
长版本:
绝对确保我们永远不会在Heroku上运行DEBUG=True,并且即使使用DEBUG=False,我们也永远不会在Heroku上运行开发服务器。来自settings.py:
DEBUG=True
DEBUG=False
RUNNING_DEV_SERVER = (len(sys.argv) > 1) and (sys.argv[1] == 'runserver')DEBUG = RUNNING_DEV_SERVERTEMPLATE_DEBUG = DEBUG# Detect the timezoneif 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()
RUNNING_DEV_SERVER = (len(sys.argv) > 1) and (sys.argv[1] == 'runserver')
DEBUG = RUNNING_DEV_SERVER
TEMPLATE_DEBUG = DEBUG
# Detect the timezone
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']
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)
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,并添加到settings.py的末尾:
djangosecurity
INSTALLED_APPS
if not (DEBUG or RUNNING_DEV_SERVER): ### Security SECURE_SSL_REDIRECT = True SECURE_CONTENT_TYPE_NOSNIFF = True SECURE_HSTS_SECONDS = 86400000 SECURE_HSTS_INCLUDE_SUBDOMAINS = True SECURE_BROWSER_XSS_FILTER = True SESSION_COOKIE_SECURE = True SESSION_COOKIE_HTTPONLY = True CSRF_COOKIE_HTTPONLY = True # May have problems with Ajax CSRF_COOKIE_SECURE = True
### Security
SECURE_SSL_REDIRECT = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_HSTS_SECONDS = 86400000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_BROWSER_XSS_FILTER = True
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
CSRF_COOKIE_HTTPONLY = True # May have problems with Ajax
CSRF_COOKIE_SECURE = True
n9vozmp48#
不需要设置自己的配置变量。这里最好使用的是$DYNO。它有文档记录,并且总是由Heroku在构建时和运行时设置。(Heroku Labs Dyno Metadata提供了一些其他选项,但它们仅在Dyno Metadata打开时设置。这些选项多年来没有更改,也没有添加到平台中,但理论上它们更“容易更改”。)
$DYNO
8条答案
按热度按时间zdwk9cvp1#
一个ENV变量似乎是最明显的方法。要么寻找一个你知道存在的ENV变量,要么设置你自己的:
字符串
更多信息:http://devcenter.heroku.com/articles/config-vars
i7uq4tfw2#
与尼尔的建议类似,我会做以下事情:
字符串
我见过一些人使用
if 'PORT' in os.environ:
,但不幸的是,当您在本地运行foreman start
时,PORT变量是存在的,所以没有办法区分使用foreman进行的本地测试和在Heroku上进行的部署。我还建议使用一个env变量:
1.在当地环境中是不可能找到的
在发布之日,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语句,因为它更明确:
型
bvn4nwqk3#
首先在heroku上设置环境变量
ON_HEROKU
:字符串
然后在
settings.py
中型
ssgvzors4#
阅读更多:https://devcenter.heroku.com/articles/config-vars
我的解决方案:
字符串
这些环境变量是持久的-它们将在部署和应用重新启动时保持不变-因此除非您需要更改值,否则只需设置一次。
然后,您可以在应用程序中测试它的存在。
型
gopyfrb35#
最可靠的方法是如上所述设置一个环境变量。如果这不可能,您可以在文件系统中查找一些迹象,但它们可能不是万无一失的
/app
-运行的文件和脚本也将在此路径下,因此您可以检查该目录的存在和/或脚本是否正在该目录下运行。/etc/heroku
/etc/hosts
可能添加了一些heroku相关的域~ $ cat /etc/hosts <snip>.dyno.rt.heroku.com
您的里程可能会有所不同
6g8kf2rb6#
DATABASE_URL
环境变量字符串
我认为你需要为你的应用启用数据库:
型
但它是免费的,而且很可能是你无论如何都要做的。
Heroku在运行其应用程序时提供此环境变量,特别是用于以下用途:
型
并不是万无一失的,因为该变量可能是本地定义的,但对于简单的情况很方便。
型
也可以显示其他可能的变量,例如:
DYNO_RAM
个WEB_CONCURRENCY
个但我不确定这些是否像
DATABASE_URL
一样被记录下来。7ajki6be7#
**短版本:**检查时区是否为UTC/GMT:
字符串
这比
if tz=='UTC\n'
更保守:如果有疑问,假设我们在生产环境中。请注意,我们将时区保存到环境变量中,因为settings.py
可能会执行多次。实际上,开发服务器执行了两次,第二次系统时区已经是'UTC'(或settings.TIMEZONE
中的任何内容)。长版本:
绝对确保我们永远不会在Heroku上运行
DEBUG=True
,并且即使使用DEBUG=False
,我们也永远不会在Heroku上运行开发服务器。来自settings.py
:型
如果你真的想在Heroku上运行开发服务器,我建议你添加一个环境变量,指定你可以运行的日期。然后只有当这个日期是今天的时候才继续。这样你就必须在开始开发工作之前更改这个变量,但是如果你忘记取消设置,第二天你仍然可以防止在生产环境中意外运行它。当然,如果您希望非常保守,也可以指定(比如说)一个1小时窗口来应用例外情况。
最后,如果你决定采用上面建议的方法,同时安装django-security,将
djangosecurity
添加到INSTALLED_APPS
,并添加到settings.py
的末尾:型
n9vozmp48#
不需要设置自己的配置变量。
这里最好使用的是
$DYNO
。它有文档记录,并且总是由Heroku在构建时和运行时设置。(Heroku Labs Dyno Metadata提供了一些其他选项,但它们仅在Dyno Metadata打开时设置。这些选项多年来没有更改,也没有添加到平台中,但理论上它们更“容易更改”。)