bash - una - Establecer variables de entorno desde el archivo de valores clave/par
variables en bash (19)
Espacios blancos en el valor.
Hay muchas respuestas excelentes aquí, pero encontré que todas carecen de soporte para espacios 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 dichos valores con soporte para líneas vacías y comentarios.
Una basada en sed y @ javier-buzzi answer :
source <(sed -e /^$/d -e /^#/d -e ''s/.*/declare -x "&"/g'' .env)
Y uno con línea de lectura en un bucle basado en la answer @ john1024
while read -r line; do declare -x "$line"; done < <(egrep -v "(^#|^/s|^$)" .env)
La clave aquí es usar declare -x
y poner la línea entre comillas dobles. No sé por qué, pero cuando reformateas el código de bucle a varias líneas, no funcionará. No soy un programador de bash, simplemente las engullí, todavía me parece mágico :)
TL; DR: ¿Cómo exporto un conjunto de pares clave / valor de un archivo de texto al entorno de shell?
Para el registro, a continuación es la versión original de la pregunta, con ejemplos.
Estoy escribiendo un script en bash que analiza archivos con 3 variables en una carpeta determinada, esta es una de ellas:
MINIENTREGA_FECHALIMITE="2011-03-31"
MINIENTREGA_FICHEROS="informe.txt programa.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 intenté usar source ./conf/$1
pero el mismo problema sigue siendo válido.
Tal vez haya alguna otra forma de hacer esto, solo necesito usar las variables de entorno del archivo que paso como argumento de mi script.
A partir 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
Aquí hay otra solución sed
, que no ejecuta eval ni requiere ruby:
source <(sed -E -n ''s/[^#]+/export &/ p'' ~/.env)
Esto agrega exportación, manteniendo comentarios en las líneas que comienzan con un comentario.
contenidos .env
A=1
#B=2
ejecución de la muestra
$ sed -E -n ''s/[^#]+/export &/ p'' ~/.env
export A=1
#export B=2
Encontré esto especialmente útil al construir un archivo para cargarlo en un archivo de unidad del sistema, con EnvironmentFile
.
El problema con su enfoque es la export
en el bucle while que está ocurriendo en un sub shell, y esas variables no estarán disponibles en el shell actual (shell primario del bucle while).
Agregue export
comando de export
en el propio archivo:
export MINIENTREGA_FECHALIMITE="2011-03-31"
export MINIENTREGA_FICHEROS="informe.txt programa.c"
export MINIENTREGA_DESTINO="./destino/entrega-prac1"
Entonces necesitas fuente en el archivo en el shell actual usando:
. ./conf/prac1
O
source ./conf/prac1
Encontré este hilo cuando intentaba reutilizar Docker --env-file
s en un shell. Su formato no es compatible con bash, pero es simple: name=value
, sin comillas, sin sustitución. También ignoran líneas en blanco y #
comentarios.
No podía tenerlo totalmente compatible con Posix, pero aquí hay uno que debería funcionar en shells similares a bash (probado en zsh en OSX 10.12.5 y bash en Ubuntu 14.04):
while read -r l; 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 sintaxis de paso (un
FOO
desnudo)
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 mi consola de rieles.
gabrielf ideó 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 #
, use esto (gracias al comentario de Pete ):
export $(grep -v ''^#'' .env | xargs)
Y si desea unset
todas las variables definidas en el archivo, use esto:
unset $(grep -v ''^#'' .env | sed -E ''s/(.*)=.*//1/'' | xargs)
Actualizar:
Para manejar también valores con espacios, usa:
export $(grep -v ''^#'' .env | xargs -d ''/n'')
en sistemas GNU o:
export $(grep -v ''^#'' .env | xargs -0)
en los sistemas BSD.
He actualizado la respuesta del usuario 4040650 porque es a la vez simple y permite comentarios en el archivo (es decir, líneas que comienzan con #), lo cual es muy conveniente para mí, ya que se pueden agregar comentarios que expliquen las variables. Solo reescribiendo en el contexto de la pregunta original.
Si el script está escrito 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 gnu.org/software/bash/manual/html_node/The-Set-Builtin.html :
Esta estructura es tan complicada 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] [argumento ...] set [+ abefhkmnptuvxBCEHPT] [+ o option-name] [argumento ...]
Si no se proporcionan opciones o argumentos, set muestra los nombres y valores de todas las funciones y variables de shell, ordenados según 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 muestran las variables de shell.
Cuando se suministran opciones, establecen o anulan atributos de 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 subsiguientes.
Y esto también:
El uso de ''+'' en lugar de ''-'' hace que estas opciones se desactiven. Las opciones también se pueden usar al invocar el shell. El conjunto actual de opciones se puede encontrar en $ -.
La opción allexport
se menciona en un par de otras respuestas aquí, para las cuales set -a
es el acceso directo. Adquirir el .env realmente es mejor que recorrer las líneas y exportar, ya que permite comentarios, líneas en blanco e incluso variables de entorno generadas por 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
}
Más simple:
- agarrar el contenido del archivo
- elimina cualquier línea en blanco (solo en caso de que hayas separado algunas cosas)
- eliminar cualquier comentario (solo en caso de que hayas añadido algunos ...)
- Añadir
export
a todas las líneas. -
eval
todo
eval $(cat .env | sed -e /^$/d -e /^#/d -e ''s/^/export /'')
Otra opción (no tienes que ejecutar eval
(gracias a @Jaydeep)):
export $(cat .env | sed -e /^$/d -e /^#/d | xargs)
Por último, si desea que su vida sea REALMENTE fácil, agregue esto a su ~/.bash_profile
:
function source_envfile() { export $(cat $1 | sed -e /^$/d -e /^#/d | xargs); }
(¡ASEGÚRESE DE QUE source_envfile .env
SUS CONFIGURACIONES DE BASH! source ~/.bash_profile
o ... simplemente haga una nueva pestaña / ventana y el problema se solucione) lo llama así: source_envfile .env
Mejorando la respuesta de Silas Paul
exportar las variables en una subshell las hace locales al comando.
(export $(cat .env | xargs) && rails c)
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
Invocando
source .env; echo $USER; echo $PASS
Consulte https://unix.stackexchange.com/questions/79068/how-to-export-variables-that-are-set-all-at-once
Puede usar su script original para establecer las variables, pero necesita llamarlo de la siguiente manera (con un punto independiente):
. ./minientrega.sh
También podría haber un problema con el cat | while read
cat | while read
enfoque. Yo recomendaría usar 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
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 launch.json
usando la propiedad envFile
:
"configurations": [
{
"name": "Launch server.js with .env",
"type": "node",
"request": "launch",
"envFile": "${workspaceRoot}/.env",
...
}
]
Si recibe un error porque una de sus variables contiene un valor que contiene espacios en blanco, puede intentar restablecer el IFS
(Separador de campo interno) de bash en /n
para que bash interprete el resultado de cat .env
como una lista de parámetros para la env
ejecutable.
Ejemplo:
IFS=$''/n''; env $(cat .env) rails c
Ver también:
Tengo problemas con las soluciones sugeridas anteriormente:
- La solución de @ anubhava hace que la escritura de archivos de configuración amigables de bash sea muy molesta muy rápido, y además, es posible que no desee exportar siempre su configuración.
- La solución de @Silas Paul se rompe cuando tienes variables que tienen espacios u otros caracteres que funcionan bien en valores entre comillas, pero
$()
hace que se desordenen.
Aquí está mi solución, que sigue siendo una OMI bastante terrible, y no resuelve el problema de "exportar solo a un hijo" abordado por Silas (aunque probablemente pueda ejecutarlo en una sub-shell para limitar el alcance):
source .conf-file
export $(cut -d= -f1 < .conf-file)
-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
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 genera todas las opciones actuales en un formato que luego puede ejecutar bash. También es práctico: set -o
por sí mismo, genera todas sus opciones actuales en un formato amigable para el usuario.
eval $(cat .env | sed ''s/^/export /'')
set -a
. ./env.txt
set +a
Si env.txt
es como:
VAR1=1
VAR2=2
VAR3=3
...