2012-02-21 8 views
33

Ho una webapp Django, e vorrei verificare se è in esecuzione sullo stack Heroku (per l'abilitazione condizionale del debug, ecc.) Esiste un modo semplice per farlo? Una variabile di ambiente, forse?Come posso rilevare l'ambiente di Heroku?

So che probabilmente posso farlo anche al contrario - cioè, ha rilevato se è in esecuzione su una macchina per sviluppatori, ma che semplicemente non "suona bene".

risposta

21

Una variabile ENV sembra il modo più ovvio per farlo. O cercare un var ENV che si sa esiste, o impostare il proprio:

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

più a: http://devcenter.heroku.com/articles/config-vars

+0

Grazie, non avevo notato che è possibile impostare in questo modo ancora variabili d'ambiente. Questo sembra il modo giusto per farlo. – aviraldg

+2

scorciatoia: on_heroku = 'DYNO' in os.environ –

+2

NON utilizzare on_heroku = 'DYNO' in os.environ come suggerito da tinchou. Quella variabile d'ambiente non è impostata durante determinate azioni buildpack, come quando collectstatic viene eseguito automaticamente per una build di django. Questo è quasi impossibile eseguire il debug - stai molto meglio usando la soluzione di cui sopra. – patr1ck

16

Simile a quello che Neil ha suggerito, vorrei fare le seguenti operazioni:

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

Ho visto alcune persone usare if 'PORT' in os.environ: Ma la cosa sfortunata è che la variabile PORT è presente quando si esegue foreman start localmente, quindi non c'è modo di distinguere tra test locali con caposquadra e implementazione su Heroku.

Consiglio anche utilizzando uno dei env vars che:

  1. Heroku è fuori dalla scatola (piuttosto che l'impostazione e il controllo per il proprio)
  2. è improbabile che sia trovato nel vostro locale ambiente

alla data del distacco, Heroku ha le seguenti variabili: environ

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

In genere vado con if 'DYNO' in os.environ:, perché sembra essere il più specifico di Heroku (chi altro userebbe il termine dyno, giusto?).

E ho anche preferisco formattarlo come un'istruzione if-else, perché è più esplicito:

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

per sicurezza dovresti probabilmente 'DEBUG = False' di default se lo stai facendo sicuramente. Qualcosa come "DEBUG = False; se non "DYNO" in os.environ: debug = True' forse? – crobar

0

Per saperne di più su di esso qui: https://devcenter.heroku.com/articles/config-vars

La mia soluzione:

$ heroku config:set HEROKU=1 

Queste variabili di ambiente sono persistenti: rimarranno al loro posto attraverso i deployment e i riavvii dell'app, quindi, a meno che non sia necessario modificare i valori, è necessario impostarli una sola volta.

Quindi è possibile testare la sua presenza nella tua app.:

>>> 'HEROKU' in os.environ 
True 
10

Prima impostare la variabile d'ambiente ON_HEROKU su Heroku:

$ heroku config:set ON_HEROKU=1 

Poi nel settings.py

import os 

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

Preferisco la soluzione 'DYNO' (o l'ho impostata sull'interfaccia utente web, non con' config: set') poiché questo sarà 'True' su' heroku local' troppo, il che significa che non possiamo usarlo per testare se in esecuzione su localhost o no. – OJFord

+0

@OllieFord Non ottengo 'DYNO' su' heroku local', quindi ho dovuto aggiungere esplicitamente 'DYNO = Dummy' nel mio' .env' (Qualsiasi valore va bene visto che stiamo controllando solo l'esistenza di env. variabile) –

-1

Versione corta: verifica che il fuso orario è 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)' 

Questo è più prudente di if tz=='UTC\n': in caso di dubbio, supporre che siamo in produzione. Si noti che stiamo salvando il fuso orario in una variabile di ambiente perché settings.py può essere eseguito più di una volta. Infatti, il server di sviluppo lo esegue due volte, e la seconda volta che il fuso orario del sistema è già 'UTC' (o qualsiasi cosa sia in settings.TIMEZONE).

Versione lunga:

facendo assolutamente sicuri che non abbiamo mai eseguito su Heroku con DEBUG=True, e che non abbiamo mai eseguire il server di sviluppo su Heroku anche con DEBUG=False. Da 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() 

Se davvero si vuole eseguire il server di sviluppo su Heroku, ti suggerisco di aggiungere una variabile di ambiente che specifica la data in cui è possibile farlo. Quindi procedi solo se questa data è oggi. In questo modo dovrai modificare questa variabile prima di iniziare il lavoro di sviluppo, ma se dimentichi di disinserirlo, il giorno successivo sarai comunque protetto dalla sua esecuzione accidentale in produzione. Naturalmente, se vuoi essere super-conservatore, puoi anche specificare, ad esempio, una finestra di 1 ora quando si applicano le eccezioni.

Infine, se avete deciso di adottare l'approccio suggerito sopra, mentre si è in esso, installare anche django-sicurezza, aggiungere djangosecurity-INSTALLED_APPS, e aggiungere alla fine del vostro settings.py:

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 
-1

DATABASE_URL variabile d'ambiente

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

Penso che è necessario per attivare il database per la vostra applicazione con:

heroku addons:create heroku-postgresql:hobby-dev 

ma è gratuito e probabilmente quello che farai comunque.

Heroku rende questa variabile di ambiente disponibile durante l'esecuzione di sue applicazioni, in particolare per l'utilizzo come:

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'), 
     } 
    } 

Non infallibile come quella variabile potrebbe essere definita a livello locale, ma comoda per i casi semplici.

heroku run env 

potrebbe anche mostrare altre possibili variabili quali:

  • DYNO_RAM
  • WEB_CONCURRENCY

ma non sono sicuro se questi sono documentati come DATABASE_URL.

+0

@Downvoters si prega di spiegare in modo da poter imparare e migliorare le informazioni ;-) –

+0

La variabile di ambiente 'DATABASE_URL' sta diventando più comune e non utilizzata solo da Heroku. È sempre meno probabile che sia accurato con il passare del tempo. – Rebs

0

Il modo più affidabile sarebbe quello di impostare una variabile di ambiente come sopra. Se questo non è possibile, ci sono alcuni segni si possono cercare nel filesystem, ma non possono essere/non sono infallibili

  • casi Heroku hanno tutti il ​​percorso /app - i file e gli script che eseguono anche sotto questo, quindi puoi verificare la presenza della directory e/o che gli script vengano eseguiti da sotto.

  • C'è una directory vuota /etc/heroku

  • /etc/hosts può avere un po 'di domini legati Heroku aggiunto ~ $ cat /etc/hosts <snip>.dyno.rt.heroku.com

Ognuna di queste può e possono cambiare in qualsiasi momento.

tuo chilometraggio può variare