Ha hatékonyan akarod kezelni a webes alkalmazásokat a fejlesztés és a gyártás során, meg kell értened a környezeti változókat.
Ez nem volt mindig így. Néhány évvel ezelőtt még szinte senki sem konfigurálta a Rails-alkalmazásait környezeti változókkal. De aztán jött a Heroku.
A Heroku bevezette a fejlesztőket a 12-faktoros alkalmazás-megközelítésbe. A 12-faktoros alkalmazás manifesztumukban számos legjobb gyakorlatot ismertetnek a könnyen telepíthető alkalmazások létrehozásához. A környezeti változókról szóló szakasz különösen nagy hatással volt rájuk.
A tizenkétfaktoros alkalmazás a konfigurációt környezeti változókban (gyakran env vars vagy env) tárolja. Az env vars könnyen módosítható a telepítések között anélkül, hogy bármilyen kódot megváltoztatnánk; a konfigurációs fájlokkal ellentétben kicsi az esélye annak, hogy véletlenül bekerüljenek a kódrepóba; és az egyéni konfigurációs fájlokkal vagy más konfigurációs mechanizmusokkal, mint például a Java System Properties, ellentétben ezek nyelv- és operációs rendszer-agnosztikus szabványok.
Minden eddiginél több Rubyista használ környezeti változókat. De gyakran ez egy kocsis kari módon történik. Úgy használjuk ezeket a dolgokat, hogy nem igazán értjük, hogyan működnek.
Ez a bejegyzés megmutatja, hogyan működnek valójában a környezeti változók – és ami talán még fontosabb, hogyan NEM működnek. Megvizsgáljuk továbbá a környezeti változók kezelésének néhány leggyakoribb módját a Rails-alkalmazásokban. Lássunk hozzá!
MEGJEGYZÉS: A környezeti változók biztosításáról itt olvashatsz.
- Minden folyamatnak saját környezeti változói vannak
- A környezeti változók meghalnak a folyamatukkal együtt
- Egy folyamat a környezeti változókat a szülőjétől kapja
- A szülők testre szabhatják a gyermekeiknek küldött környezeti változókat
- Children can’t set their parents’ environment variables
- A környezet megváltoztatása nem szinkronizálódik a futó folyamatok között
- A shell csak egy felhasználói felület a környezeti változó rendszerhez.
- A környezeti változók NEM azonosak a héjváltozókkal
- A környezeti változók kezelése a gyakorlatban
- Figaro
- Dotenv
- Secrets.yml?
- Plain old Linux
Minden folyamatnak saját környezeti változói vannak
Minden programnak, amelyet a szerveren futtatsz, van legalább egy folyamata. Ez a folyamat saját környezeti változókat kap. Ha egyszer már rendelkezik velük, a folyamaton kívül semmi sem változtathatja meg őket.
A kezdők érthető hibája, hogy azt hiszik, hogy a környezeti változók valahogyan a szerver egészére érvényesek. Az olyan szolgáltatások, mint a Heroku, biztos, hogy úgy tűnik, mintha a környezeti változók beállítása egyenértékű lenne a lemezen lévő konfigurációs fájl szerkesztésével. A környezeti változók azonban egyáltalán nem olyanok, mint a konfigurációs fájlok.
Minden program, amelyet a szerveren futtatunk, saját környezeti változókat kap abban a pillanatban, amikor elindítjuk.
Minden folyamatnak megvan a saját környezete.
A környezeti változók meghalnak a folyamatukkal együtt
Volt már olyan, hogy beállítottál egy környezeti változót, újraindítottad, és azt vetted észre, hogy eltűnt? Mivel a környezeti változók a folyamatokhoz tartoznak, ez azt jelenti, hogy amikor a folyamat kilép, a környezeti változók eltűnnek.
Ezt úgy láthatod, ha egy környezeti változót beállítasz egy IRB munkamenetben, bezárod azt, és megpróbálod elérni a változót egy 2. irb munkamenetben.
Amikor egy folyamat leáll, a környezeti változói elvesznek
Ez ugyanaz az elv, ami miatt a szerver újraindításakor vagy a shellből való kilépéskor a környezeti változók elvesznek. Ha azt akarod, hogy a munkamenetek között megmaradjanak, akkor valamilyen konfigurációs fájlban kell tárolnod őket, például .bashrc
.
Egy folyamat a környezeti változókat a szülőjétől kapja
Minden folyamatnak van egy szülője. Ez azért van, mert minden programot egy másik programnak kell elindítania.
Ha a bash shell segítségével indítod el a vim-et, akkor a vim szülője a shell. Ha a Rails alkalmazásod az imagemagick-et használja egy kép azonosítására, akkor a identify
program szülője a Rails alkalmazásod lesz.
Child processes inherit env vars from their parent
Az alábbi példában a $MARCO környezeti változó értékét állítom be az IRB folyamatomban. Ezután back-tickkel kiírom a shell-t és visszahallgatom a változó értékét.
Mivel az IRB az imént létrehozott shell szülőfolyamata, megkapja a $MARCO környezeti változó másolatát.
A Ruby-ban beállított környezeti változókat a gyermekfolyamatok öröklik
A szülők testre szabhatják a gyermekeiknek küldött környezeti változókat
Egy gyermek alapértelmezés szerint minden olyan környezeti változó másolatát megkapja, amellyel a szülője rendelkezik. De a szülőnek van erre befolyása.
A parancssorból használhatjuk az env programot. A bash-ben pedig van egy speciális szintaxis arra, hogy az env vars-t úgy állítsuk be a gyermeknél, hogy a szülőnél nem állítjuk be.
Az env parancsot használjuk a gyermek környezeti változóinak beállítására anélkül, hogy a szülőnél beállítanánk őket
Ha a Ruby-ből shellingelünk, akkor egyéni környezeti változókat is megadhatunk a gyermek folyamatnak anélkül, hogy az ENV hash-t szemetelnénk. Csak használd a következő szintaxist a system
metódussal:
How to pass custom environment variables into Ruby’s system method
Children can’t set their parents’ environment variables
Mivel a gyerekek csak másolatot kapnak a szülők környezeti változóiról, a gyerek által végzett változtatások nem lesznek hatással a szülőre.
A környezeti változókat “értékkel” és nem “hivatkozással”
Itt a back-tick szintaxist használjuk a shell out-hoz és megpróbálunk beállítani egy környezeti változót. Bár a változót a gyermek számára beállítjuk, az új érték nem jut el a szülőhöz.
A gyermek folyamatok nem tudják megváltoztatni a szülők env vars
A környezet megváltoztatása nem szinkronizálódik a futó folyamatok között
A lenti példában az IRB két példányát futtatom egymás mellett. Egy változó hozzáadása az egyik IRB munkamenet környezetéhez nincs hatással a másik IRB munkamenetre.
A környezeti változó hozzáadása egy folyamathoz nem változtatja meg a többi folyamatot
A shell csak egy felhasználói felület a környezeti változó rendszerhez.
A rendszer maga az OS kernel része. Ez azt jelenti, hogy a shellnek nincs varázslatos hatalma a környezeti változók felett. Ugyanazokat a szabályokat kell követnie, mint minden más futtatott programnak.
A környezeti változók NEM azonosak a héjváltozókkal
Az egyik legnagyobb félreértés azért történik, mert a héjak saját “helyi” héjváltozórendszert biztosítanak. A helyi változók használatának szintaxisa gyakran ugyanaz, mint a környezeti változóké. És a kezdők gyakran összekeverik a kettőt.
De a helyi változók nem másolódnak át a gyermekváltozókba.
A környezeti változók nem ugyanazok, mint a shellváltozók
Nézzünk egy példát. Először is beállítok egy MARCO nevű helyi héjváltozót. Mivel ez egy helyi változó, nem másolódik át egyetlen gyermekfolyamatba sem. Következésképpen, amikor megpróbálom a Ruby-n keresztül kiírni, nem működik.
A következőkben az export paranccsal a helyi változót környezeti változóvá alakítom. Most már minden új folyamatba átmásolódik, amit ez a shell létrehoz. Most már a környezeti változó elérhető a Ruby számára.
A helyi változók nem elérhetők a gyermekfolyamatok számára. Az exportálás a helyi változót környezeti változóvá alakítja.
A környezeti változók kezelése a gyakorlatban
Hogyan működik mindez a való világban? Nézzünk egy példát:
Tegyük fel, hogy két Rails-alkalmazás fut egy számítógépen. A Honeybadgert használod arra, hogy ezeket az alkalmazásokat figyeld a kivételek szempontjából. De belefutottál egy problémába.
A Honeybadger API kulcsát a $HONEYBADGER_API_KEY környezeti változóban szeretnéd tárolni. De a két alkalmazásodnak két különböző API kulcsa van.
Hogyan lehet egy környezeti változónak két különböző értéke?
Most remélem, már tudod a választ. Mivel az env vars per-process, és az én két rails alkalmazásom különböző folyamatokban fut, nincs ok, amiért ne lehetne mindkettőnek saját értéke a $HONEYBADGER_API_KEY számára.
Most már csak az a kérdés, hogyan állítsuk be. Szerencsére van néhány gem, ami ezt nagyon egyszerűvé teszi.
Figaro
Ha telepíted a Figaro gemet a Rails alkalmazásodba, minden érték, amit a config/application.yml-be beírsz, indításkor betöltődik a ruby ENV hash-ba.
Egyszerűen telepíted a gemet:
# Gemfilegem "figaro"
És elkezdesz elemeket hozzáadni az application.yml-hez. Nagyon fontos, hogy ezt a fájlt hozzáadd a .gitignore fájlodhoz, nehogy véletlenül commitold a titkaidat.
# config/application.ymlHONEYBADGER_API_KEY: 12345
Dotenv
A dotenv gem nagyon hasonló a Figaróhoz, kivéve, hogy a környezeti változókat a .env, és nem használ YAML-t.
Egyszerűen telepítsd a gem-et:
# Gemfilegem 'dotenv-rails'
És add hozzá a konfigurációs értékeidet a .env – és győződj meg róla, hogy a git figyelmen kívül hagyja a fájlt, nehogy véletlenül publikáld a githubon.
HONEYBADGER_API_KEY=12345
Ezután hozzáférhetsz az értékekhez a Ruby ENV hash-odban
ENV
A shellben is futtathatsz parancsokat az előre definiált env vars készleteddel, például így:
dotenv ./my_script.sh
Secrets.yml?
Sorry. A Secrets.yml – bár klassz – nem állít be környezeti változókat. Tehát nem igazán helyettesíti az olyan gemeket, mint a Figaro és a dotenv.
Plain old Linux
A környezeti változók egyedi készleteit is fenn lehet tartani alkalmazásonként, alapvető linuxos parancsokkal. Az egyik megközelítés az, hogy minden egyes, a szerveren futó alkalmazás egy másik felhasználó tulajdonában van. Ezután a felhasználó .bashrc állományát használhatja az alkalmazásspecifikus értékek tárolására.