Se você quer ser capaz de gerenciar efetivamente aplicações web em desenvolvimento e em produção, você tem que entender as variáveis de ambiente.

Este nem sempre foi o caso. Apenas alguns anos atrás, quase ninguém configurava suas aplicações Rails com variáveis de ambiente. Mas então Heroku aconteceu.

Heroku introduziu os desenvolvedores à abordagem da aplicação de 12 fatores. Em seu manifesto de aplicações de 12 fatores, eles apresentam muitas de suas melhores práticas para criar aplicações que são fáceis de implementar. A seção sobre variáveis de ambiente tem sido particularmente influente.

O aplicativo de doze fatores armazena a configuração em variáveis de ambiente (muitas vezes abreviada para env vars ou env). Env vars são fáceis de mudar entre deploys sem alterar nenhum código; ao contrário dos arquivos de configuração, há pouca chance deles serem verificados no repo do código acidentalmente; e ao contrário dos arquivos de configuração personalizados, ou outros mecanismos de configuração como Java System Properties, eles são um padrão de linguagem e OS-agnostic.

Mais Rubyists estão usando variáveis de ambiente do que nunca. Mas muitas vezes é de uma forma de carga-culty. Estamos usando essas coisas sem realmente entender como elas funcionam.

Este post irá mostrar como as variáveis de ambiente realmente funcionam – e talvez mais importante, como elas NÃO funcionam. Também vamos explorar algumas das formas mais comuns de gerenciar variáveis de ambiente em suas aplicações Rails. Vamos começar!

NOTE: Você pode ler sobre proteger variáveis de ambiente aqui.

Todos os processos têm seu próprio conjunto de variáveis de ambiente

Todos os programas que você executa no seu servidor têm pelo menos um processo. Esse processo tem seu próprio conjunto de variáveis de ambiente. Uma vez que ele as tem, nada fora desse processo pode mudá-las.

Um erro compreensível que os iniciantes cometem é pensar que as variáveis de ambiente são de alguma forma em todo o servidor. Serviços como Heroku certamente fazem parecer que definir as variáveis de ambiente é o equivalente a editar um arquivo de configuração no disco. Mas variáveis de ambiente não são nada como arquivos de configuração.

Todos os programas que você executa no seu servidor recebem seu próprio conjunto de variáveis de ambiente no momento em que você o inicia.

Todos os processos têm seu próprio ambiente. Cada processo tem o seu próprio ambiente.

As variáveis de ambiente morrem com o seu processo

Você já definiu uma variável de ambiente, reinicializou e descobriu que ela tinha desaparecido? Como as variáveis de ambiente pertencem a processos, ou seja, sempre que o processo sai, sua variável de ambiente desaparece.

Você pode ver isso definindo uma variável de ambiente em uma sessão do IRB, fechando-a e tentando acessar a variável em uma 2ª sessão do irb.

Quando um processo se desliga, suas variáveis de ambiente são perdidas Quando um processo se desliga, suas variáveis de ambiente são perdidas

Este é o mesmo princípio que faz você perder variáveis de ambiente quando seu servidor é reinicializado, ou quando você sai do seu shell. Se você quiser que elas persistam durante as sessões, você tem que armazená-las em algum tipo de arquivo de configuração como .bashrc .

Um processo obtém suas variáveis de ambiente de seu pai

Todos os processos têm um pai. Isto porque cada programa tem que ser iniciado por algum outro programa.

Se você usar sua shell bash para lançar o vim, então o pai do vim é a shell. Se sua aplicação Rails usa imagemagick para identificar uma imagem, então o pai do programa identify será sua aplicação Rails.

Processos infantis herdam vars env do pai delesProcessos infantis herdam vars env do pai deles

No exemplo abaixo, estou definindo o valor da variável de ambiente $MARCO no meu processo IRB. Então eu uso back-ticks para shell out e ecoar o valor dessa variável.

Desde que IRB é o processo pai da shell que acabei de criar, ele recebe uma cópia da variável de ambiente $MARCO.

>As variáveis de ambiente definidas em Ruby são herdadas por processos filhosAs variáveis de ambiente definidas em Ruby são herdadas por processos filhos

Os pais podem personalizar as variáveis de ambiente enviadas aos seus filhos

Por padrão, um filho receberá cópias de cada variável de ambiente que seu pai possui. Mas o pai tem controle sobre isso.

Da linha de comando, você pode usar o programa env. E na bash há uma sintaxe especial para definir variáveis de ambiente para uma criança sem defini-las no pai.

Utilize o comando env para definir variáveis de ambiente para uma criança sem defini-las no paiUtilize o comando env para definir variáveis de ambiente para uma criança sem defini-las no pai

Se você estiver usando o shelling de dentro do Ruby você também pode fornecer variáveis de ambiente personalizadas para o processo da criança sem litter seu hash ENV. Basta usar a seguinte sintaxe com o método system:

Como passar variáveis de ambiente personalizadas para o método de sistema do Ruby Como passar variáveis de ambiente personalizadas para o método de sistema do Ruby

As crianças não podem definir as variáveis de ambiente dos pais

Desde que as crianças obtenham apenas cópias das variáveis de ambiente dos pais, as alterações feitas pela criança não têm qualquer efeito sobre os pais.

As variáveis de ambiente são "passadas por valor" e não "por referência"As variáveis de ambiente são “passadas por valor” e não “por referência”

Aqui, nós usamos a sintaxe do back-tick para shell out e tentamos definir uma variável de ambiente. Enquanto a variável será definida para a criança, o novo valor não borbulha até o pai.

Processos infantis não podem mudar seus pais env varsProcessos infantis não podem mudar seus pais env vars

Alterações para o ambiente não sincronizam entre processos em execução

No exemplo abaixo estou rodando duas cópias de IRB lado a lado. Adicionar uma variável ao ambiente de uma sessão IRB não tem nenhum efeito na outra sessão IRB.

Adicionar uma variável de ambiente a um processo não a altera para outros processosAdicionar uma variável de ambiente a um processo não a altera para outros processos

A sua shell é apenas uma IU para o sistema de variáveis de ambiente.

O sistema em si é parte do kernel do SO. Isso significa que o shell não tem nenhum poder mágico sobre as variáveis de ambiente. Ele tem que seguir as mesmas regras que qualquer outro programa que você executa.

As variáveis de ambiente NÃO são as mesmas que as variáveis da shell

Um dos maiores mal-entendidos acontece porque as shells fornecem seus próprios sistemas de variáveis de shell “locais”. A sintaxe para usar variáveis locais é frequentemente a mesma que para variáveis de ambiente. E iniciantes frequentemente confundem as duas.

Mas variáveis locais não são copiadas para as crianças.

Ambiente variáveis não são as mesmas que variáveis shellAmbiente variáveis não são as mesmas que variáveis shell

Vamos dar uma olhada em um exemplo. Primeiro eu defino uma variável shell local chamada MARCO. Já que esta é uma variável local, ela não é copiada para nenhum processo filho. Consequentemente, quando tento imprimi-la via Ruby, ela não funciona.

Next, eu uso o comando export para converter a variável local em uma variável de ambiente. Agora ela é copiada para cada novo processo que esta shell cria. Agora a variável de ambiente está disponível para Ruby.

A variáveis locais não estão disponíveis para processos filhos. Export converte a variável local para uma variável de ambiente. Variáveis locais não estão disponíveis para os processos filhos. Export converte a variável local para uma variável de ambiente.

Gerenciar variáveis de ambiente na prática

Como tudo isso funciona no mundo real? Vamos fazer um exemplo:

Suponha que você tenha dois aplicativos Rails rodando em um único computador. Você está usando o Honeybadger para monitorar esses aplicativos para exceções. Mas você encontrou um problema.

Você gostaria de armazenar sua chave Honeybadger API na variável de ambiente $HONEYBADGER_API_KEY. Mas as suas duas aplicações têm duas chaves de API separadas.

Como pode uma variável de ambiente ter dois valores diferentes?

Até agora espero que saiba a resposta. Como as variáveis de ambiente são por processo, e minhas duas aplicações Rails são executadas em processos diferentes, não há razão para que cada uma delas não possa ter seu próprio valor para $HONEYBADGER_API_KEY.

Agora a única questão é como configurá-la. Felizmente existem algumas gems que tornam isso realmente fácil.

Figaro

Quando você instalar a gem Figaro na sua aplicação Rails, quaisquer valores que você digitar em config/application.yml serão carregados no hash ruby ENV na inicialização.

Você apenas instala a gem:

# Gemfilegem "figaro"

E começa a adicionar itens em application.yml. É muito importante que você adicione este arquivo ao seu .gitignore, para que você não cometa acidentalmente seus segredos.

>

# config/application.ymlHONEYBADGER_API_KEY: 12345

Dotenv

A gema dotenv é muito similar ao Figaro, exceto que ela carrega variáveis de ambiente do .env, e não usa YAML.

Just install the gem:

# Gemfilegem 'dotenv-rails'

E adicione seus valores de configuração a .env – e certifique-se de ignorar o arquivo para que você não o publique acidentalmente ao github.

>

HONEYBADGER_API_KEY=12345

Você pode então acessar os valores no seu hash Ruby ENV

>

ENV

>

Você também pode executar comandos na shell com seu conjunto pré-definido de vars de env como so:

dotenv ./my_script.sh

Secrets.yml?

Sorry. Secrets.yml – embora legal – não define variáveis de ambiente. Então não é realmente um substituto para gems como Figaro e dotenv.

Plain old Linux

Também é possível manter conjuntos únicos de variáveis de ambiente por aplicativo usando comandos básicos do linux. Uma abordagem é ter cada aplicação em execução no seu servidor sendo de propriedade de um usuário diferente. Você pode então usar o .bashrc do usuário para armazenar valores específicos da aplicação.

Deixe uma resposta

O seu endereço de email não será publicado.