Jos haluat pystyä tehokkaasti hallitsemaan web-sovelluksia kehityksessä ja tuotannossa, sinun on ymmärrettävä ympäristömuuttujia.
Tämä ei ole aina ollut näin. Vielä muutama vuosi sitten tuskin kukaan konfiguroi Rails-sovelluksiaan ympäristömuuttujien avulla. Mutta sitten tapahtui Heroku.
Heroku esitteli kehittäjille 12-faktorisen sovelluslähestymistavan. Heidän 12-tekijäsovellusmanifestissaan he esittävät paljon parhaita käytäntöjään helposti käyttöönotettavien sovellusten luomiseen. Ympäristömuuttujia koskeva osio on ollut erityisen vaikutusvaltainen.
Kahdentoista tekijän sovellus tallentaa konfiguraation ympäristömuuttujiin (usein lyhennettynä env vars tai env). Env-tavaroita on helppo muuttaa käyttöönottojen välillä muuttamatta koodia; toisin kuin konfigurointitiedostoissa, on pieni mahdollisuus, että ne tarkistetaan koodirepoon vahingossa; ja toisin kuin mukautetut konfigurointitiedostot tai muut konfigurointimekanismit, kuten Javan järjestelmäominaisuudet, ne ovat kieli- ja käyttöjärjestelmä-agnostinen standardi.
Monet rubyistit käyttävät ympäristömuuttujia enemmän kuin koskaan. Mutta usein se on cargo-culty tavalla. Käytämme niitä ymmärtämättä kunnolla, miten ne toimivat.
Tässä postauksessa näytetään, miten ympäristömuuttujat oikeasti toimivat – ja mikä ehkä vielä tärkeämpää, miten ne EIVÄT toimi. Tutustumme myös joihinkin yleisimpiin tapoihin hallita ympäristömuuttujia Rails-sovelluksissasi. Aloitetaan!
Huomautus: Voit lukea ympäristömuuttujien suojaamisesta täältä.
- Jokaiseen prosessiin kuuluu oma joukko ympäristömuuttujia
- Ympäristömuuttujat kuolevat prosessinsa mukana
- Prosessi saa ympäristömuuttujansa vanhemmaltaan
- Vanhemmat voivat muokata lapsilleen lähetettäviä ympäristömuuttujia
- Lapset eivät voi asettaa vanhempiensa ympäristömuuttujia
- Ympäristön muutokset eivät synkronoidu käynnissä olevien prosessien välillä
- Kuoretulkkisi (shell) on pelkkä käyttöliittymä ympäristömuuttujajärjestelmälle.
- Ympäristömuuttujat EIVÄT ole sama asia kuin komentotulkin muuttujat
- Ympäristömuuttujien hallinta käytännössä
- Figaro
- Dotenv
- Secrets.yml?
- Plain old Linux
Jokaiseen prosessiin kuuluu oma joukko ympäristömuuttujia
Jokaiseen palvelimellasi ajettavaan ohjelmaan kuuluu ainakin yksi prosessi. Tämä prosessi saa oman joukon ympäristömuuttujia. Kun sillä on ne, mikään prosessin ulkopuolinen ei voi muuttaa niitä.
Ymmärrettävä virhe, jonka aloittelijat tekevät, on luulla, että ympäristömuuttujat ovat jotenkin koko palvelimen laajuisia. Herokun kaltaiset palvelut saavat varmasti näyttämään siltä, että ympäristömuuttujien asettaminen vastaa levyllä olevan konfigurointitiedoston muokkaamista. Ympäristömuuttujat eivät kuitenkaan ole mitään konfigurointitiedostojen kaltaista.
Jokainen palvelimella ajettava ohjelma saa oman joukon ympäristömuuttujia sillä hetkellä, kun se käynnistetään.
Jokaisella prosessilla on oma ympäristönsä.
Ympäristömuuttujat kuolevat prosessinsa mukana
Oletko koskaan asettanut ympäristömuuttujaa, käynnistänyt sen uudelleen ja huomannut, että se oli kadonnut? Koska ympäristömuuttujat kuuluvat prosesseihin, se tarkoittaa, että aina kun prosessi lopetetaan, ympäristömuuttujasi katoaa.
Voit havaita tämän asettamalla ympäristömuuttujan yhdessä IRB-istunnossa, sulkemalla sen ja yrittämällä käyttää muuttujaa toisessa irb-istunnossa.
Kun prosessi sammuu, sen ympäristömuuttujat häviävät
Tämä on sama periaate, joka aiheuttaa ympäristömuuttujien häviämisen palvelimen uudelleenkäynnistyksen tai komentotulkista poistumisen yhteydessä. Jos haluat, että ympäristömuuttujat säilyvät istuntojen yli, ne on tallennettava johonkin asetustiedostoon, kuten .bashrc
.
Prosessi saa ympäristömuuttujansa vanhemmaltaan
Jokaisella prosessilla on vanhempi. Tämä johtuu siitä, että jokaisen ohjelman täytyy käynnistyä jostain toisesta ohjelmasta.
Jos käynnistät vimin bash-selaimella, vimin vanhempi on selain. Jos Rails-sovelluksesi käyttää imagemagickia kuvan tunnistamiseen, niin identify
-ohjelman identify
vanhempi on Rails-sovelluksesi.
Child processes inherit env vars from their parent
Allekirjoittamassani esimerkissä asetan IRB-prosessissani $MARCO-ympäristömuuttujan arvon. Sitten käytän back-tickiä shell-outiin ja kaikuin tuon muuttujan arvon.
Koska IRB on äsken luomani shellin emoprosessi, se saa kopion $MARCO-ympäristömuuttujasta.
Rubyssä asetetut ympäristömuuttujat periytyvät lapsiprosesseille
Vanhemmat voivat muokata lapsilleen lähetettäviä ympäristömuuttujia
Vakiintuneesti lapsi saa kopiot jokaisesta ympäristömuuttujasta, joka sen vanhemmalla on. Mutta vanhempi voi hallita tätä.
Komentoriviltä voit käyttää env-ohjelmaa. Ja bashissa on erityinen syntaksi, jolla voit asettaa env-varat lapselle asettamatta niitä vanhemmalle.
Käytä komentoa env asettaaksesi ympäristömuuttujia lapselle asettamatta niitä vanhemmalle
Jos kuoriudut Ruby-ohjelman sisältä, voit myös antaa lapsiprosessille mukautettuja ympäristömuuttujia ilman, että se roskaantuisi ENV-hashista. Käytä vain seuraavaa syntaksia system
-metodin kanssa:
Miten omia ympäristömuuttujia välitetään Rubyn systeemimetodiin
Lapset eivät voi asettaa vanhempiensa ympäristömuuttujia
Sen vuoksi, että lapset saavat vain kopiot vanhempiensa ympäristömuuttujista, lapsen tekemät muutokset eivät vaikuta vanhempaan.
Ympäristömuuttujat siirretään ”arvon mukaan”, ei ”viittauksen mukaan”
Tässä käytämme back-tick-syntaksia, jolla kuoriudutaan ja yritetään asettaa ympäristömuuttuja. Vaikka muuttuja asetetaan lapselle, uusi arvo ei siirry vanhemmalle prosessille.
Lapsiprosessit eivät voi muuttaa vanhempiensa env-arvoja
Ympäristön muutokset eivät synkronoidu käynnissä olevien prosessien välillä
Alhaalla olevassa esimerkissä käytän kahta kopiota IRB:stä vierekkäin. Muuttujan lisääminen yhden IRB-istunnon ympäristöön ei vaikuta mitenkään toiseen IRB-istuntoon.
Ympäristömuuttujan lisääminen yhdelle prosessille ei muuta sitä muille prosesseille
Kuoretulkkisi (shell) on pelkkä käyttöliittymä ympäristömuuttujajärjestelmälle.
Järjestelmä itsessään on osa käyttöjärjestelmän ydintä. Se tarkoittaa, että shellillä ei ole mitään maagista valtaa ympäristömuuttujiin. Sen on noudatettava samoja sääntöjä kuin kaikkien muidenkin suorittamiesi ohjelmien.
Ympäristömuuttujat EIVÄT ole sama asia kuin komentotulkin muuttujat
Yksi suurimmista väärinkäsityksistä johtuu siitä, että komentotulkit tarjoavat omat ”paikalliset” komentotulkin muuttujajärjestelmänsä. Paikallisten muuttujien käytön syntaksi on usein sama kuin ympäristömuuttujien. Ja aloittelijat sekoittavat nämä kaksi usein keskenään.
Mutta paikallisia muuttujia ei kopioida lapsiin.
Ympäristömuuttujat eivät ole sama asia kuin komentotulkin muuttujat
Katsotaanpa esimerkkiä. Asetan ensin paikallisen komentotulkkimuuttujan nimeltä MARCO. Koska tämä on paikallinen muuttuja, sitä ei kopioida mihinkään lapsiprosesseihin. Näin ollen, kun yritän tulostaa sen Rubyn kautta, se ei onnistu.
Seuraavaksi käytän export-komentoa muuttaakseni paikallisen muuttujan ympäristömuuttujaksi. Nyt se kopioidaan jokaiseen uuteen prosessiin, jonka tämä komentotulkki luo. Nyt ympäristömuuttuja on Rubyn käytettävissä.
Paikalliset muuttujat eivät ole lapsiprosessien käytettävissä. Export muuntaa paikallisen muuttujan ympäristömuuttujaksi.
Ympäristömuuttujien hallinta käytännössä
Miten tämä kaikki toimii reaalimaailmassa? Tehdäänpä esimerkki:
Esitellään, että sinulla on kaksi Rails-sovellusta käynnissä yhdellä tietokoneella. Käytät Honeybadgeria valvomaan näitä sovelluksia poikkeusten varalta. Mutta olet törmännyt ongelmaan.
Haluat tallentaa Honeybadgerin API-avaimen $HONEYBADGER_API_KEY-ympäristömuuttujaan. Mutta kahdella sovelluksellasi on kaksi erillistä API-avainta.
Miten yhdellä ympäristömuuttujalla voi olla kaksi eri arvoa?
Nyt toivottavasti tiedät vastauksen. Koska ympäristömuuttujat ovat prosessikohtaisia, ja kahta rails-sovellustani ajetaan eri prosesseissa, ei ole mitään syytä, miksei niillä kummallakin voisi olla omaa arvoa $HONEYBADGER_API_KEY:lle.
Nyt ainoa kysymys on, miten se asetetaan. Onneksi on olemassa muutama helmi, jotka tekevät tästä todella helppoa.
Figaro
Kun asennat Figaro-helmen Rails-sovellukseesi, kaikki arvot, jotka syötät config/application.yml-tiedostoon, ladataan ruby-ENV-hashiin käynnistyksen yhteydessä.
Asennat vain helmen:
# Gemfilegem "figaro"
Ja alat lisäämään kohteita application.yml-tiedostoon. On erittäin tärkeää, että lisäät tämän tiedoston .gitignore-tiedostoosi, jotta et vahingossa committaa salaisuuksiasi.
# config/application.ymlHONEYBADGER_API_KEY: 12345
Dotenv
Dotenv-jalokivi on hyvin samanlainen kuin Figaro, paitsi että se lataa ympäristömuuttujat .env, eikä se käytä YAML:ää.
Asenna gem:
# Gemfilegem 'dotenv-rails'
Ja lisää konfiguraatioarvot .env – ja varmista, että git sivuuttaa tiedoston, jotta et vahingossa julkaise sitä githubiin.
HONEYBADGER_API_KEY=12345
Voit sitten käyttää arvoja Ruby ENV hashissasi
ENV
Voit myös ajaa komentoja komentotulkissa ennalta määrittelemälläsi joukolla env-arvoja esimerkiksi näin:
dotenv ./my_script.sh
Secrets.yml?
Sorry. Secrets.yml – vaikka onkin siisti – ei aseta ympäristömuuttujia. Se ei siis oikeastaan korvaa Figaron ja dotenv:n kaltaisia helmiä.
Plain old Linux
Mahdollista on myös ylläpitää uniikkeja ympäristömuuttujien sarjoja sovelluskohtaisesti käyttämällä Linuxin peruskomentoja. Yksi lähestymistapa on, että jokainen palvelimella suoritettava sovellus on eri käyttäjän omistuksessa. Voit sitten käyttää käyttäjän .bashrc-tiedostoa sovelluskohtaisten arvojen tallentamiseen.