Establecer variables de entorno desde el archivo

Estoy escribiendo un script en bash que analiza archivos con 3 variables en una determinada carpeta, esta es una de ellas:

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

Este archivo se almacena en ./conf/prac1

Mi script minientrega.sh luego analiza el archivo usando este código:

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

Pero cuando ejecuto minientrega.sh prac1 en la línea de comandos, no establece las variables de entorno

También probé usando source ./conf/$1 pero el mismo problema todavía se aplica

Tal vez haya alguna otra forma de hacerlo, solo necesito usar las variables de entorno del archivo que paso como argumento de mi script.

El problema con su enfoque es que la export en el ciclo while ocurre en un subconjunto, y esa variable no estará disponible en el shell actual (shell primario del ciclo while).

Agregar comando de export en el archivo en sí:

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

Luego, debe buscar en el archivo el shell actual usando:

 . ./conf/prac1 

O

 source ./conf/prac1 

Esto podría ser útil:

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

La razón por la que uso esto es si quiero probar cosas .env en la consola de mis Rails.

gabrielf propuso una buena manera de mantener las variables locales. Esto resuelve el problema potencial al pasar de un proyecto a otro.

 env $(cat .env | xargs) rails 

He probado esto con bash 3.2.51(1)-release


Actualizar:

Para ignorar las líneas que comienzan con # , usa esto (gracias al comentario de Pete ):

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

Y si quiere unset todas las variables definidas en el archivo, use esto:

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

Actualizar:

Para manejar valores con espacios, use:

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

en sistemas GNU o:

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

en sistemas BSD.

-o allexport permite -o allexport todas las siguientes definiciones de variables. +o allexport deshabilita esta característica.

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

Si env.txt es como:

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

La opción de allexport se menciona en un par de otras respuestas aquí, para las cuales el set -a es el atajo. La obtención del .env realmente es mejor que hacer un bucle sobre las líneas y exportar, ya que permite comentarios, líneas en blanco e incluso variables de entorno generadas por los comandos. Mi .bashrc incluye lo siguiente:

 # .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 } 

Aquí hay otra solución sed , que no ejecuta eval o requiere ruby:

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

Esto agrega exportación, manteniendo los comentarios en líneas comenzando con un comentario.

contenidos .env

 A=1 #B=2 

ejecución de muestra

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

Encontré esto especialmente útil al construir un archivo para cargar en un archivo de unidad systemd, con EnvironmentFile .

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

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

Esto guardará / restaurará sus opciones originales, cualesquiera que sean.

El uso de set -o allexport tiene la ventaja de omitir correctamente los comentarios sin una expresión regular.

set +o por sí mismo da salida a todas sus opciones actuales en un formato que bash puede ejecutar más tarde. También es útil: set -o solo, emite todas sus opciones actuales en formato amigable para los humanos.

Mejorando la respuesta de Silas Paul

exportar las variables en una subshell las hace locales al comando.

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

He actualizado la respuesta de user4040650 porque es simple y permite comentarios en el archivo (es decir, líneas que comienzan con #), lo cual es muy deseable para mí, ya que se pueden agregar comentarios que expliquen las variables. Simplemente reescribiendo en el contexto de la pregunta original.

Si el script se llama como se indica: minientrega.sh prac1 , entonces minientrega.sh podría tener:

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

Lo siguiente fue extraído de la documentación del conjunto :

Este built-in es tan complicado que merece su propia sección. set le permite cambiar los valores de las opciones de shell y establecer los parámetros posicionales, o mostrar los nombres y valores de las variables de shell.

set [–abefhkmnptuvxBCEHPT] [-o option-name] [argument …] set [+ abefhkmnptuvxBCEHPT] [+ o option-name] [argument …]

Si no se proporcionan opciones o argumentos, set muestra los nombres y valores de todas las funciones y variables de shell, ordenadas de acuerdo con la configuración regional actual, en un formato que puede reutilizarse como entrada para configurar o restablecer las variables establecidas actualmente. Las variables de solo lectura no se pueden restablecer. En el modo POSIX, solo se enumeran las variables del shell.

Cuando se suministran opciones, establecen o desactivan los atributos del shell. Las opciones, si se especifican, tienen los siguientes significados:

-a Cada variable o función que se crea o modifica recibe el atributo de exportación y se marca para exportar al entorno de los comandos posteriores.

Y esto también:

Usar ‘+’ en lugar de ‘-‘ hace que estas opciones se apaguen. Las opciones también se pueden usar al invocar el shell. El conjunto actual de opciones se puede encontrar en $ -.

Simpler:

  1. agarrar el contenido del archivo
  2. elimina cualquier línea en blanco (solo en caso de que hayas separado algunas cosas)
  3. eliminar cualquier comentario (solo en caso de que hayas agregado …)
  4. agregue la export a todas las líneas
  5. eval todo

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

Otra opción (no es necesario ejecutar eval (gracias a @Jaydeep)):

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

Por último, si quieres que tu vida sea REALMENTE fácil, agrégala a tu ~/.bash_profile :

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

(ASEGÚRESE DE VOLVER A USTED SU CONFIGURACIÓN DE BASH !!! source ~/.bash_profile or .. solo haga una nueva pestaña / ventana y resuelva el problema) lo llama así: source_envfile .env

Puede usar su script original para establecer las variables, pero debe llamarlo de la siguiente manera (con un punto independiente):

 . ./minientrega.sh 

También puede haber un problema con cat | while read cat | while read acercamiento. Yo recomendaría utilizar el enfoque while read line; do .... done < $FILE while read line; do .... done < $FILE .

Aquí hay un ejemplo de trabajo:

 > 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 

Sobre la base de otras respuestas, aquí hay una manera de exportar solo un subconjunto de líneas en un archivo, incluidos los valores con espacios como PREFIX_ONE="a word" :

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

Tengo problemas con las soluciones sugeridas anteriormente:

  • La solución de @anubhava hace que escribir archivos de configuración amistosa bash sea muy molesto muy rápido, y también, es posible que no desee exportar siempre su configuración.
  • La solución de @Silas Paul se rompe cuando tiene variables que tienen espacios u otros caracteres que funcionan bien en valores cotizados, pero $() hace un lío.

Aquí está mi solución, que todavía es bastante terrible, IMO, y no resuelve el problema de “exportar solo a un niño” abordado por Silas (aunque probablemente puedas ejecutarlo en un subconjunto para limitar el scope):

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

Espacios en blanco en el valor

Aquí hay muchas respuestas excelentes, pero las encontré todas falta de soporte para el espacio en blanco en el valor:

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

He encontrado 2 soluciones que funcionan con esos valores con soporte para líneas vacías y comentarios.

Una basada en sed y @ javier-buzzi responden :

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

Y uno con línea de lectura en un bucle basado en @ john1024 respuesta

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

La clave aquí está en usar declare -x y poner línea entre comillas dobles. No sé por qué, pero cuando vuelves a formatear el código del bucle en varias líneas, no funciona: no soy un progtwigdor de bash, me acabo de engullir, sigue siendo mágico para mí 🙂

Si obtiene un error porque una de sus variables contiene un valor que contiene espacios en blanco, puede intentar restablecer el IFS de Bash (Separador interno de campos) a \n para permitir que bash interprete el resultado cat .env como una lista de parámetros para el env ejecutable.

Ejemplo:

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

Ver también:

Encontré este hilo cuando estaba intentando reutilizar Docker --env-file s en un shell. Su formato no es compatible con bash, pero es simple: name=value , sin citas, sin sustitución. También ignoran líneas en blanco y # comentarios.

No pude conseguir que Posix compatible, pero aquí hay uno que debería funcionar en conchas bash (probado en zsh en OSX 10.12.5 y bash en Ubuntu 14.04):

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

No manejará tres casos en el ejemplo de los documentos vinculados anteriormente:

  • bash: export: `123qwe=bar': not a valid identifier
  • bash: export: `org.spring.config=something': not a valid identifier
  • y no manejará la syntax de paso (un FOO desnudo)

Si desea cargar su archivo .env en el proceso en ejecución dentro del código de Visual Studio, puede agregar una referencia a su archivo .env en su archivo launch.json utilizando la propiedad envFile :

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

Mi .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 

Invocar:

 source .env; echo $USER; echo $PASS 

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