Definir variables ​​de ambiente do arquivo

Eu estou escrevendo um script no bash que analisa arquivos com 3 variables ​​em uma determinada pasta, esta é uma delas:

MINIENTREGA_FECHALIMITE="2011-03-31" MINIENTREGA_FICHEROS="informe.txt programa.c" MINIENTREGA_DESTINO="./destino/entrega-prac1" 

Este arquivo é armazenado em ./conf/prac1

Meu script minientrega.sh, em seguida, analisa o arquivo usando este código:

 cat ./conf/$1 | while read line; do export $line done 

Mas quando executo minientrega.sh prac1 na linha de comando, ele não define as variables ​​de ambiente

Eu também tentei usar o source ./conf/$1 mas o mesmo problema ainda se aplica

Talvez haja alguma outra maneira de fazer isso, eu só preciso usar as variables ​​de ambiente do arquivo que eu passo como o argumento do meu script.

Problema com a sua abordagem é a export no loop while está acontecendo em um sub shell, e essas variables ​​não estarão disponíveis no shell atual (shell pai do loop while).

Adicione export comando de export no próprio arquivo:

 export MINIENTREGA_FECHALIMITE="2011-03-31" export MINIENTREGA_FICHEROS="informe.txt programa.c" export MINIENTREGA_DESTINO="./destino/entrega-prac1" 

Então você precisa de fonte no arquivo no shell atual usando:

 . ./conf/prac1 

OU

 source ./conf/prac1 

Isso pode ser útil:

 export $(cat .env | xargs) && rails c 

Razão pela qual eu uso isso é se eu quiser testar coisas .env no meu console de rails.

gabrielf criou uma boa maneira de manter as variables ​​locais. Isso resolve o problema em potencial ao passar de projeto para projeto.

 env $(cat .env | xargs) rails 

Eu testei isso com o bash 3.2.51(1)-release


Atualizar:

Para ignorar linhas que começam com # , use isto (graças ao comentário de Pete ):

 export $(grep -v '^#' .env | xargs) 

E se você quiser unset todas as variables ​​definidas no arquivo, use isto:

 unset $(grep -v '^#' .env | sed -E 's/(.*)=.*/\1/' | xargs) 

Atualizar:

Para também manipular valores com espaços, use:

 export $(grep -v '^#' .env | xargs -d '\n') 

em sistemas GNU ou:

 export $(grep -v '^#' .env | xargs -0) 

em sistemas BSD.

-o allexport permite que todas as definições de variables ​​a seguir sejam exportadas. +o allexport desativa esse recurso.

 set -o allexport source conf-file set +o allexport 
 set -a . ./env.txt set +a 

Se env.txt é como:

 VAR1=1 VAR2=2 VAR3=3 ... 

A opção allexport é mencionada em algumas outras respostas aqui, para as quais set -a é o atalho. A obtenção do .env é realmente melhor do que o loop de linhas e a exportação, pois permite comentários, linhas em branco e até mesmo variables ​​de ambiente geradas por comandos. Meu .bashrc inclui o seguinte:

 # .env loading in the shell dotenv () { set -a [ -f .env ] && . .env set +a } # Run dotenv on login dotenv # Run dotenv on every new directory cd () { builtin cd $@ dotenv } 

Aqui está outra solução sed , que não executa eval ou requer ruby:

 source <(sed -E -n 's/[^#]+/export &/ p' ~/.env) 

Isso adiciona exportação, mantendo comentários nas linhas que começam com um comentário.

conteúdo .env

 A=1 #B=2 

corrida de amostra

 $ sed -E -n 's/[^#]+/export &/ p' ~/.env export A=1 #export B=2 

Achei isso especialmente útil ao construir esse arquivo para carregar em um arquivo de unidade do systemd, com EnvironmentFile .

 eval $(cat .env | sed 's/^/export /') 

SAVE=$(set +o) && set -o allexport && . .env; eval "$SAVE"

Isso salvará / restaurará suas opções originais, sejam elas quais forem.

Usando set -o allexport tem a vantagem de pular corretamente os comentários sem um regex.

set +o por si só exibe todas as suas opções atuais em um formato que o bash pode executar posteriormente. Também é útil: set -o por si só, exibe todas as suas opções atuais em formato amigável para humanos.

Melhorando na resposta de Silas Paul

exportar as variables ​​em um subshell as torna locais para o comando.

(export $(cat .env | xargs) && rails c)

Eu tenho upvoted resposta do user4040650 porque é simples, e permite comentários no arquivo (ou seja, linhas começando com #), que é altamente desejável para mim, como comentários explicando as variables ​​podem ser adicionadas. Apenas reescrevendo no contexto da pergunta original.

Se o script for chamado conforme indicado: minientrega.sh prac1 , então minientrega.sh poderia ter:

 set -a # export all variables created next source $1 set +a # stop exporting # test that it works echo "Ficheros: $MINIENTREGA_FICHEROS" 

O seguinte foi extraído da documentação do conjunto :

Este builtin é tão complicado que merece sua própria seção. set permite que você altere os valores das opções do shell e defina os parâmetros posicionais ou exiba os nomes e valores das variables ​​do shell.

set [–abefhkmnptuvxBCEHPT] [-o nome da opção] [argumento…] set [+ abefhkmnptuvxBCEHPT] [+ o nome da opção] [argumento…]

Se nenhuma opção ou argumento for fornecido, set exibe os nomes e valores de todas as variables ​​e funções do shell, classificadas de acordo com o local atual, em um formato que pode ser reutilizado como input para configurar ou redefinir as variables ​​atualmente configuradas. Variáveis ​​de somente leitura não podem ser redefinidas. No modo POSIX, apenas as variables ​​do shell são listadas.

Quando as opções são fornecidas, elas definem ou desativam os atributos do shell. Opções, se especificado, possuem os seguintes significados:

-a Cada variável ou function que é criada ou modificada recebe o atributo de exportação e é marcada para exportação para o ambiente de comandos subseqüentes.

E isso também:

Usar ‘+’ em vez de ‘-‘ faz com que essas opções sejam desativadas. As opções também podem ser usadas na invocação do shell. O conjunto atual de opções pode ser encontrado em $ -.

Mais simples:

  1. pegue o conteúdo do arquivo
  2. remova todas as linhas em branco (apenas caso você tenha separado algumas coisas)
  3. remova qualquer comentário (apenas caso você tenha adicionado alguns …)
  4. adicione export a todas as linhas
  5. eval a coisa toda

eval $(cat .env | sed -e /^$/d -e /^#/d -e 's/^/export /')

Outra opção (você não precisa executar o eval (graças ao @Jaydeep)):

 export $(cat .env | sed -e /^$/d -e /^#/d | xargs) 

Por último, se você quiser tornar a sua vida muito fácil, adicione isso ao seu ~/.bash_profile :

function source_envfile() { export $(cat $1 | sed -e /^$/d -e /^#/d | xargs); }

(CERTIFIQUE-SE DE RECARREGAR SUAS CONFIGURAÇÕES DE BASH !!! source ~/.bash_profile ou .. basta fazer uma nova aba / janela e problema resolvido) você chama assim: source_envfile .env

Você pode usar seu script original para definir as variables, mas você precisa chamá-lo da seguinte maneira (com ponto autônomo):

 . ./minientrega.sh 

Também pode haver um problema com cat | while read cat | while read abordagem. Eu recomendaria usar a abordagem while read line; do .... done < $FILE while read line; do .... done < $FILE .

Aqui está um exemplo de trabalho:

 > cat test.conf VARIABLE_TMP1=some_value > cat run_test.sh #/bin/bash while read line; do export "$line"; done < test.conf echo "done" > . ./run_test.sh done > echo $VARIABLE_TMP1 some_value 

Com base em outras respostas, aqui está uma maneira de exportar apenas um subconjunto de linhas em um arquivo, incluindo valores com espaços como PREFIX_ONE="a word" :

 set -a . <(grep '^[ ]*PREFIX_' conf-file) set +a 

Tenho problemas com as soluções sugeridas anteriormente:

  • A solução do @ anubhava torna a escrita de arquivos de configuração amigáveis ​​bash muito irritantes muito rápido, e também – você pode não querer sempre exportar sua configuração.
  • A solução @Silas Paul quebra quando você tem variables ​​que possuem espaços ou outros caracteres que funcionam bem em valores entre aspas, mas $() faz uma bagunça.

Aqui está a minha solução, que ainda é um IMO terrível – e não resolve o problema “exportar apenas para um filho” abordado pelo Silas (embora você possa executá-lo em um sub-shell para limitar o escopo):

 source .conf-file export $(cut -d= -f1 < .conf-file) 

Espaços em branco no valor

Há muitas ótimas respostas aqui, mas descobri que todas elas não têm suporte para o espaço em branco no valor:

 DATABASE_CLIENT_HOST=host db-name db-user 0.0.0.0/0 md5 

Eu encontrei duas soluções que funcionam com esses valores com suporte para linhas vazias e comentários.

Um baseado na resposta sed e @ javier-buzzi:

 source <(sed -e /^$/d -e /^#/d -e 's/.*/declare -x "&"/g' .env) 

E um com linha de leitura em um loop baseado em @ john1024 resposta

 while read -r line; do declare -x "$line"; done < <(egrep -v "(^#|^\s|^$)" .env) 

A chave aqui é usar declare -x e colocar linha entre aspas duplas. Eu não sei por que, mas quando você reformatar o código de loop para várias linhas, ele não funcionará - eu não sou um programador bash, apenas engolei tudo isso, ainda é mágica para mim 🙂

Se você está recebendo um erro porque uma de suas variables ​​contém um valor que contém espaços em branco, você pode tentar redefinir o IFS (Internal Field Separator) do bash para \n para permitir que o bash interprete o resultado cat .env como uma lista de parâmetros para o env executável.

Exemplo:

 IFS=$'\n'; env $(cat .env) rails c 

Veja também:

Me deparei com este segmento quando eu estava tentando reutilizar Docker --env-file s em um shell. Seu formato não é compatível com o bash, mas é simples: name=value , sem cotação, sem substituição. Eles também ignoram linhas em branco e # comentários.

Eu não conseguia chegar a ele compatível com posix, mas aqui está um que deve funcionar em shells bash-like (testado em zsh no OSX 10.12.5 e bash no Ubuntu 14.04):

 while read -rl; do export "$(sed 's/=.*$//' <<<$l)"="$(sed -E 's/^[^=]+=//' <<<$l)"; done < <(grep -E -v '^\s*(#|$)' your-env-file) 

Ele não manipulará três casos no exemplo dos documentos vinculados acima:

  • bash: export: `123qwe=bar': not a valid identifier
  • bash: export: `org.spring.config=something': not a valid identifier
  • e não irá lidar com a syntax de passagem (um FOO simples)

Se você deseja carregar seu arquivo .env no processo em execução dentro do código do Visual Studio, é possível adicionar uma referência ao seu arquivo .env em seu launch.json usando a propriedade envFile :

 "configurations": [ { "name": "Launch server.js with .env", "type": "node", "request": "launch", "envFile": "${workspaceRoot}/.env", ... } ] 

Meu .env:

 #!/bin/bash set -a # export all variables #comments as usual, this is a bash script USER=foo PASS=bar set +a #stop exporting variables 

Invocando:

 source .env; echo $USER; echo $PASS 

Referência https://unix.stackexchange.com/questions/79068/how-to-export-variables-that-are-set-all-at-once