TL; DR: Como exportar um conjunto de pares de chave / valor de um arquivo de texto para o ambiente do shell?
Para o registro, abaixo está a versão original da pergunta, com exemplos.
Estou escrevendo um script no bash que analisa arquivos com 3 variáveis em uma determinada pasta, este é um deles:
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 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, não define as variáveis de ambiente
Eu também tentei usar, source ./conf/$1
mas o mesmo problema ainda se aplica
Talvez exista alguma outra maneira de fazer isso, eu só preciso usar as variáveis de ambiente do arquivo que passo como argumento do meu script.
bash
variables
environment-variables
hugo19941994
fonte
fonte
Respostas:
Problema com a sua abordagem é a
export
dowhile
laço está acontecendo em um sub shell, e aqueles variável não estará disponível no shell atual (shell pai de while loop).Adicionar
export
comando no próprio arquivo:Em seguida, você precisa obter o arquivo no shell atual usando:
OU
fonte
export
não é o ideal, o problema também pode ser corrigido simplesmente usando redirecionamento de entrada no loop:while read line; do ... ; done < ./conf/$1
.< <(commands that generate output)
set -o allexport
export
iria quebrá-lo para coisas como Java, Systemd, ou outras ferramentasawk '{print "export " $0}' envfile
comando de conveniência paraIsso pode ser útil:
A razão pela qual eu uso isso é se eu quero testar
.env
coisas no meu console de rails.O gabrielf criou uma boa maneira de manter as variáveis locais. Isso resolve o problema potencial ao passar de um projeto para outro.
Eu testei isso com
bash 3.2.51(1)-release
Atualizar:
Para ignorar as linhas que começam com
#
, use isto (graças ao comentário de Pete ):E se você quiser
unset
todas as variáveis definidas no arquivo, use o seguinte:Atualizar:
Para também manipular valores com espaços, use:
em sistemas GNU - ou:
em sistemas BSD.
fonte
export $(cat .env)
mas não sei como lidar com os espaços.-d
para definir o delimitador, por isso estou tentandoenv $(cat .env | xargs -d '\n') rails
, mas ainda assim erros com um arquivo não encontrado se.env
tiver espaços. Alguma idéia de por que isso não funciona?eval $(cat .env) rails
-o allexport
permite que todas as seguintes definições de variáveis sejam exportadas.+o allexport
desativa esse recurso.fonte
.env
arquivo tiver comentários. Obrigado!set -o allexport; source conf-file; set +o allexport
set -a; . conf-file; set +a
.Se
env.txt
é como:Explicações -a é equivalente a allexport . Em outras palavras, todas as atribuições de variáveis no shell são exportadas para o ambiente (para serem usadas por vários processos filhos). Mais informações podem ser encontradas na documentação do conjunto :
fonte
-a
é equivalente aallexport
. Em outras palavras, todas as atribuições de variáveis no shell sãoexport
inseridas no ambiente (para serem usadas por vários processos filhos). Consulte também este artigo gnu.org/software/bash/manual/html_node/The-Set-Builtin.htmlA
allexport
opção é mencionada em algumas outras respostas aqui, para as quaisset -a
é o atalho. Fornecer o .env realmente é melhor do que repetir linhas e exportar porque permite comentários, linhas em branco e até variáveis de ambiente geradas por comandos. Meu .bashrc inclui o seguinte:fonte
VAR=
.fonte
eval $(cat .env | sed 's/^[^$]/export /')
permite ter linhas vazias para melhor legibilidade.cat .env | sed 's/^[^$]/export /'
retira o caráter inicial. Ou seja, para um arquivoA=foo\nB=bar\n
que receboexport =foo\nexport =bar\n
. Isso funciona melhor para pular linhas em branco:cat .env | sed '/^$/! s/^/export /'
.cat
em ambos os casos:eval $(sed 's/^/export /' .env)
funciona tão bem.)Eu achei a maneira mais eficiente é:
Explicação
Quando temos um
.env
arquivo como este:correr
xargs < .env
vai ficarkey=val foo=bar
então teremos um
export key=val foo=bar
e é exatamente o que precisamos!Limitação
fonte
env
produzem esse formato.Aqui está outra
sed
solução, que não executa eval ou requer ruby:Isso adiciona exportação, mantendo os comentários nas linhas começando com um comentário.
conteúdo .env
amostra de execução
Achei isso especialmente útil ao construir um arquivo para carregar em um arquivo de unidade systemd, com
EnvironmentFile
.fonte
Promovi a resposta de user4040650 porque é simples e permite comentários no arquivo (ou seja, linhas começando com #), o que é altamente desejável para mim, pois é possível adicionar comentários explicando as variáveis. Apenas reescrevendo no contexto da pergunta original.
Se o script for chamado conforme indicado
minientrega.sh prac1
:, o minientrega.sh poderá ter:O seguinte foi extraído da documentação do conjunto :
E isso também:
fonte
Melhorando a resposta de Silas Paul
exportar as variáveis em um subshell as torna locais para o comando.
(export $(cat .env | xargs) && rails c)
fonte
(set -a; source dev.env; set +a; rails c)
para também obter os benefícios do fornecimento (por exemplo, o script pode ser executado).SAVE=$(set +o | grep allexport) && set -o allexport && . .env; eval "$SAVE"
Isso salvará / restaurará suas opções originais, sejam elas quais forem.
O uso
set -o allexport
tem a vantagem de ignorar corretamente os comentários sem uma regex.set +o
por si só gera todas as suas opções atuais em um formato que o bash pode executar posteriormente. Também útil:set -o
por si só, gera todas as suas opções atuais em formato amigável para humanos.fonte
exec env -i bash
limparia o ambiente existente antes de chamar,eval
se você precisar desconfigurar variáveis definidas apenas dentro.env
.A maneira mais curta que encontrei:
Seu
.env
arquivo:Então apenas
Bônus: Por ser uma linha curta, é muito útil em
package.json
arquivosfonte
VARIABLE_NAME="A_VALUE"
Mais simples:
export
a todas as linhaseval
a coisa todaeval $(cat .env | sed -e /^$/d -e /^#/d -e 's/^/export /')
Outra opção (você não precisa executar
eval
(graças a @Jaydeep)):Por fim, se você quiser tornar sua vida MUITO fácil, adicione isso ao seu
~/.bash_profile
:function source_envfile() { export $(cat $1 | sed -e /^$/d -e /^#/d | xargs); }
(TENHA CERTEZA DE RECOLOCAR AS CONFIGURAÇÕES DO BASH !!!
source ~/.bash_profile
ou .. basta criar uma nova guia / janela e resolver o problema), você chama assim:source_envfile .env
fonte
source <( echo $(sed -E -n 's/[^#]+/ &/ p' <(echo "${2}" | tr -d '\r')) );
. De alguma forma, o gitlab salva a variável secreta com um retorno de carro do Windows, então eu tive que apará-la comtr -d '\r'
.Você pode usar seu script original para definir as variáveis, mas é necessário chamá-lo da seguinte maneira (com ponto independente):
Também pode haver um problema com a
cat | while read
abordagem. Eu recomendaria usar a abordagemwhile read line; do .... done < $FILE
.Aqui está um exemplo de trabalho:
fonte
test.conf
como um arquivo de script. Isso torna tudo melhor. É mais seguro não permitir scripts, a menos que você realmente precise, especialmente se alguém não perceber o que está acontecendo (ou esquecer).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"
:fonte
Aqui está minha variante:
em comparação com as soluções anteriores:
.env
não são expostos ao chamador)set
opçõesset -a
.
vez desource
evitar o basismo.env
carregamento falharfonte
set -a && . ./.env && "$@" && echo "your comand here"
Eu trabalho com docker-composite e
.env
arquivos no Mac e queria importar o arquivo para o.env
meu bash shell (para teste), e a "melhor" resposta aqui foi acionar a seguinte variável:.env
Solução
Então acabei usando
eval
e envolvendo meus env var defs entre aspas simples.Versão do Bash
fonte
Meu .env:
Invocando:
Referência /unix/79068/how-to-export-variables-that-are-set-all-at-once
fonte
Tenho problemas com as soluções sugeridas anteriormente:
$()
que causam confusão.Aqui está minha solução, que ainda é muito terrível para a IMO - e não resolve o problema "exportar apenas para um filho" abordado por Silas (embora você provavelmente possa executá-la em um sub-shell para limitar o escopo):
fonte
Meus requisitos eram:
export
prefixos (para compatibilidade com dotenv)Versão de trabalho completa compilada a partir das respostas acima:
fonte
Primeiro, crie um arquivo de ambiente que terá todo o par de valores-chave dos ambientes abaixo e o nomeie como quiser no meu caso,
env_var.env
Em seguida, crie um script que exporte todas as variáveis de ambiente para o ambiente python como abaixo e nomeie-o como
export_env.sh
Esse script pegará o primeiro argumento como o arquivo de ambiente, exportará toda a variável de ambiente nesse arquivo e executará o comando depois disso.
USO:
fonte
Me deparei com esse encadeamento quando estava tentando reutilizar o Docker
--env-file
s em uma concha. Seu formato não é compatível com o bash, mas é simplesname=value
:, sem citação, sem substituição. Eles também ignoram linhas em branco e#
comentários.Eu não consegui obtê-lo compatível com posix, mas aqui está um que deve funcionar em shell do tipo bash (testado no zsh no OSX 10.12.5 e no bash no Ubuntu 14.04):
Ele não tratará 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
FOO
)fonte
Espaços em branco no valor
Há muitas ótimas respostas aqui, mas eu encontrei todas sem suporte para espaço em branco no valor:
Encontrei 2 soluções que funcionam com esses valores com suporte para linhas e comentários vazios.
Um baseado na resposta sed e @ javier-buzzi :
E um com linha de leitura em um loop baseado na resposta @ john1024
A chave aqui está em usar
declare -x
e colocar linha entre aspas duplas. Eu não sei por que, mas quando você reformata o código do loop em várias linhas, ele não funciona - eu não sou programador de bash, apenas juntei esses, ainda é mágico para mim :)fonte
sed
solução para fazê-la funcionar. Mas primeiro alguma explicação:-e
é a abreviação de--expression
, que apenas informased
quais operações executar.-e /^$/d
exclui as linhas vazias da saída (não o arquivo).-e /^#/d
exclui os comentários do bash (linhas que começam com #) da saída.'s/.*/declare -x "&"/g'
substitui (substitui) as linhas restantes pordeclare -x "ENV_VAR="VALUE""
. Quando você compra isso, pelo menos para mim, não funciona. Em vez disso, tive que usarsource <(sed -e /^$/d -e /^#/d -e 's/.*/declare -x &/g' .env)
para remover o"
invólucro extra .ENV_VAR="lorem ipsum"
,ENV_VAR=lorem ipsum
sem aspas, no arquivo .env. Agora não sei por que, mas isso provavelmente foi problemático em outras ferramentas que analisam esse arquivo. E em vez delorem ipsum
terminar com"lorem ipsum"
valor - entre aspas. Thx para as explicações :)ENV_VAR="lorem ipsum"
. No meu caso de uso, meu provedor de hospedagem gera esse arquivo com base em algumas opções de configuração definidas e insere aspas duplas. Então, sou forçado a contornar isso. Obrigado por sua ajuda aqui - economizei muito tempo tentando descobrir assed
opções corretas !tente algo assim
fonte
Como funciona
.env
arquivo. Todas as variáveis serão exportadas para o ambiente atual.declare -x VAR="val"
que exportaria cada uma das variáveis para o ambiente.Recursos
.env
pode ter comentários.env
pode ter linhas vazias.env
não requer cabeçalho ou rodapé especial, como nas outras respostas (set -a
eset +a
).env
não requer terexport
para todo valorfonte
Se você estiver recebendo um erro porque uma de suas variáveis contém um valor que contém espaços em branco, tente redefinir o bash's
IFS
(Internal Field Separator)\n
para permitir que o bash interprete ocat .env
resultado como uma lista de parâmetros para oenv
executável.Exemplo:
Veja também:
fonte
Meu arquivo .env se parece com:
Usando as maneiras do @henke , o valor exportado acaba contendo as aspas
"
Mas quero que o valor exportado contenha apenas:
Para corrigi-lo, edito o comando para excluir as aspas:
fonte
Este lida com espaços no RHS e pula vars 'estranhos', como definições de módulo bash (com '()' neles):
fonte