web-dev-qa-db-fra.com

Définir les variables d'environnement à partir du fichier de paires clé / valeur

TL; DR: Comment exporter un ensemble de paires clé/valeur à partir d'un fichier texte dans l'environnement Shell?


Pour mémoire, voici la version originale de la question, avec des exemples.

J'écris un script en bash qui analyse les fichiers avec 3 variables dans un certain dossier, en voici un:

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

Ce fichier est stocké dans ./conf/prac1

Mon script minientrega.sh analyse ensuite le fichier en utilisant ce code:

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

Mais lorsque j'exécute minientrega.sh prac1 en ligne de commande, les variables d'environnement ne sont pas définies.

J'ai aussi essayé d'utiliser source ./conf/$1 mais le même problème s'applique toujours

Peut-être y a-t-il un autre moyen de faire cela, je dois juste utiliser les variables d'environnement du fichier que je passe comme argument de mon script.

389
hugo19941994

Le problème avec votre approche est que la export de la boucle while se produit dans un sous-shell et que cette variable ne sera pas disponible dans le shell actuel (le shell parent de la boucle while).

Ajoutez la commande export dans le fichier lui-même:

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

Ensuite, vous devez source dans le fichier dans le shell actuel en utilisant:

. ./conf/prac1

OR

source ./conf/prac1
151
anubhava

Cela pourrait être utile:

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

La raison pour laquelle j'utilise ceci est si je veux tester .env dans ma console Rails.

gabrielf a trouvé un bon moyen de garder les variables locales. Cela résout le problème potentiel lors du passage d'un projet à l'autre.

env $(cat .env | xargs) Rails

J'ai testé cela avec bash 3.2.51(1)-release


Mise à jour:

Pour ignorer les lignes commençant par #, utilisez ceci (grâce à commentaire de Pete ):

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

Et si vous voulez unset toutes les variables définies dans le fichier, utilisez ceci:

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

Mise à jour:

Pour gérer également les valeurs avec des espaces, utilisez:

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

sur GNU systèmes - ou:

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

sur les systèmes BSD.

691
Silas Paul

-o allexport permet d'exporter toutes les définitions de variables suivantes. +o allexport désactive cette fonctionnalité.

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

Si env.txt est comme:

VAR1=1
VAR2=2
VAR3=3
...
91
Dan Kowalczyk

L'option allexport est mentionnée dans quelques réponses ici, pour laquelle set -a est le raccourci. Sourcing est vraiment meilleur que de boucler sur des lignes et d’exporter car cela permet des commentaires, des lignes vides et même des variables d’environnement générées par des commandes. Mon .bashrc comprend les éléments suivants:

# .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
}
27
gsf
eval $(cat .env | sed 's/^/export /')
23
selvan

Voici une autre solution sed, qui ne tourne pas eval et ne nécessite pas Ruby:

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

Cela ajoute export, en gardant les commentaires sur les lignes commençant par un commentaire.

contenu .env

A=1
#B=2

échantillon échantillon

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

J'ai trouvé cela particulièrement utile lors de la construction d'un tel fichier pour le chargement dans un fichier systemd unit file, avec EnvironmentFile .

20
tutuDajuju

J'ai voté la réponse de user4040650 parce que c'est à la fois simple et que cela permet des commentaires dans le fichier (c'est-à-dire les lignes commençant par #), ce qui est hautement souhaitable pour moi, car des commentaires expliquant les variables peuvent être ajoutés. Il suffit de réécrire dans le contexte de la question initiale.

Si le script est appelé comme indiqué: minientrega.sh prac1, minientrega.sh peut avoir:

set -a # export all variables created next
source $1
set +a # stop exporting

# test that it works
echo "Ficheros: $MINIENTREGA_FICHEROS"

Ce qui suit a été extrait de set documentation :

Cette construction est tellement compliquée qu'elle mérite sa propre section. set vous permet de modifier les valeurs des options du shell et de définir les paramètres de position, ou d’afficher les noms et les valeurs des variables du shell.

set [--abefhkmnptuvxBCEHPT] [-o nom-option] [argument…] set [+ abefhkmnptuvxBCEHPT] [+ o nom-option] [argument…]

Si aucune option ou argument n'est fourni, set affiche les noms et les valeurs de toutes les variables et fonctions de Shell, triés selon les paramètres régionaux en vigueur, dans un format pouvant être réutilisé en tant qu'entrée pour la définition ou la réinitialisation des variables actuellement définies. Les variables en lecture seule ne peuvent pas être réinitialisées. En mode POSIX, seules les variables Shell sont répertoriées.

Lorsque des options sont fournies, elles définissent ou non des attributs de shell. Les options, si spécifiées, ont les significations suivantes:

-a Chaque attribut ou exportation est attribué à chaque variable ou fonction créée ou modifiée et marquée pour l'exportation dans l'environnement des commandes suivantes.

Et ceci aussi:

L'utilisation de "+" plutôt que de "-" entraîne la désactivation de ces options. Les options peuvent également être utilisées lors de l'invocation du shell. L'ensemble actuel d'options peut être trouvé dans $ -.

14
Nagev

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

Cela sauvegardera/restaurera vos options d'origine, quelles qu'elles soient.

L'utilisation de set -o allexport présente l'avantage de sauter correctement les commentaires sans regex.

set +o affiche seul toutes vos options actuelles dans un format que bash pourra exécuter ultérieurement. Aussi pratique: set -o par lui-même, affiche toutes vos options actuelles dans un format convivial.

12
jwfearn

Améliorer la réponse de Silas Paul

l'exportation des variables sur un sous-shell les rend locales à la commande.

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

11
Jaydeep

Plus simple:

  1. récupérer le contenu du fichier
  2. supprime les lignes vides (en cas de séparation de certains éléments)
  3. supprimer tous les commentaires (juste en cas vous en avez ajouté ...)
  4. ajouter export à toutes les lignes
  5. eval le tout

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

Une autre option (vous n'avez pas besoin de lancer eval (merci à @Jaydeep)):

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

Enfin, si vous voulez rendre votre vie vraiment facile, ajoutez ceci à votre ~/.bash_profile:

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

(ASSUREZ-VOUS DE RECHARGER VOS PARAMÈTRES BASH !!! source ~/.bash_profile ou .. créez simplement un nouvel onglet/fenêtre et le problème sera résolu) vous l'appelez ainsi: source_envfile .env

9
Javier Buzzi

Le chemin le plus court que j'ai trouvé:

Votre fichier .env:

VARIABLE_NAME="A_VALUE"

Alors juste

. ./.env && echo ${VARIABLE_NAME}

Bonus: Comme c'est un one-liner, c'est très utile dans le fichier package.json

  "scripts": {
    "echo:variable": ". ./.env && echo ${VARIABLE_NAME}"
  }
7
Flavien Volken

En vous appuyant sur d’autres réponses, voici un moyen d’exporter uniquement un sous-ensemble de lignes d’un fichier, y compris les valeurs avec des espaces tels que PREFIX_ONE="a Word":

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

Vous pouvez utiliser votre script d'origine pour définir les variables, mais vous devez l'appeler de la manière suivante (avec un point autonome):

. ./minientrega.sh

Il pourrait également y avoir un problème avec l’approche cat | while read. Je recommanderais d'utiliser l'approche while read line; do .... done < $FILE.

Voici un exemple de travail:

> 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
5
Extrapolator

Tout d’abord, créez un fichier d’environnement contenant toutes les paires clé-valeur des environnements, comme ci-dessous, et nommez-le comme vous le souhaitez dans mon cas, son env_var.env

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

Créez ensuite un script qui exportera toutes les variables d’environnement pour l’environnement python, comme ci-dessous, et nommez-le comme export_env.sh.

#!/usr/bin/env bash

ENV_FILE="$1"
CMD=${@:2}

set -o allexport
source $ENV_FILE
set +o allexport

$CMD

Ce script utilisera le premier argument en tant que fichier d’environnement, puis exportera toutes les variables d’environnement de ce fichier, puis exécutera la commande.

SAGE:

./export_env.sh env_var.env python app.py
2
anand tripathi

Mes exigences étaient:

  • fichier .env simple sans les préfixes export (pour la compatibilité avec dotenv)
  • valeurs de soutien entre guillemets: TEXT = "alpha bravo charlie"
  • commentaires de support précédés de # et de lignes vides
  • universel pour mac/BSD et linux/GNU

Version de travail complète compilée à partir des réponses ci-dessus:

  set -o allexport
  eval $(grep -v '^#' .env | sed 's/^/export /')
  set +o allexport
1
Alex

Je travaille avec les fichiers docker-compose et .env sur Mac et je voulais importer le .env dans mon shell bash (à des fins de test), et la "meilleure" réponse a été de déclencher la variable suivante:

. env

NODE_ARGS=--expose-gc --max_old_space_size=2048

Solution

Je me suis donc retrouvé à utiliser eval et à emballer mes env var var entre guillemets simples.

eval $(grep -v -e '^#' .env | xargs -I {} echo export \'{}\')

Version Bash

$ /bin/bash --version
GNU bash, version 3.2.57(1)-release (x86_64-Apple-darwin18)
Copyright (C) 2007 Free Software Foundation, Inc.
1
Nick Grealy

Espaces blancs dans la valeur

Il y a beaucoup de bonnes réponses ici, mais j'ai trouvé qu'elles manquaient toutes de support pour les espaces dans la valeur:

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

J'ai trouvé 2 solutions qui fonctionnent avec de telles valeurs avec un support pour les lignes vides et les commentaires.

Un basé sur sed et @ javier-buzzi réponse :

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

Et une avec une ligne de lecture dans une boucle basée sur @ john1024 answer

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

La clé ici est d'utiliser declare -x et de mettre la ligne entre guillemets. Je ne sais pas pourquoi, mais lorsque vous reformatez le code de la boucle en plusieurs lignes, cela ne fonctionnera pas - je ne suis pas un programmeur bash, je viens de les engloutir, c'est toujours magique pour moi :)

1

J'ai des problèmes avec les solutions suggérées précédemment:

  • La solution de @ anubhava rend l'écriture de fichiers de configuration conviviaux pour bash très gênante, et aussi - vous ne voudrez peut-être pas toujours exporter votre configuration.
  • @Silas Paul solution casse lorsque vous avez des variables qui ont des espaces ou d'autres caractères qui fonctionnent bien dans les valeurs entre guillemets, mais $() crée un désordre.

Voici ma solution, qui est toujours très mauvaise OMI - et ne résout pas le problème de "l'exportation uniquement vers un enfant" traité par Silas (bien que vous puissiez probablement l'exécuter dans un sous-shell pour limiter la portée):

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

Si vous obtenez une erreur parce qu'une de vos variables contient une valeur contenant des espaces, vous pouvez essayer de réinitialiser le IFS (séparateur de champs interne) de bash sur \n pour laisser bash interpréter cat .env résultat sous forme de liste de paramètres pour l'exécutable env.

Exemple:

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

Voir également:

0

Je suis tombé sur ce fil lorsque j'essayais de réutiliser Docker --env-files dans un shell. Leur format n'est pas compatible bash mais c'est simple: name=value, pas de citation, pas de substitution. Ils ignorent également les lignes vides et les commentaires #.

Je ne pouvais pas tout à fait le rendre compatible posix, mais en voici un qui devrait fonctionner dans des shells de type bash (testé sous zsh sous OSX 10.12.5 et bash sous Ubuntu 14.04):

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

Il ne traitera pas trois cas dans l'exemple des documents liés ci-dessus:

  • bash: export: `123qwe=bar': not a valid identifier
  • bash: export: `org.spring.config=something': not a valid identifier
  • et il ne gérera pas la syntaxe passthrough (un FOO nu)
0
Bob Zoller

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

Invoquer:

source .env; echo $USER; echo $PASS

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

0
Tudor Ilisoi