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.
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
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.
-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
set -a
. ./env.txt
set +a
Si env.txt
est comme:
VAR1=1
VAR2=2
VAR3=3
...
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
}
eval $(cat .env | sed 's/^/export /')
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.
A=1
#B=2
$ 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
.
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 $ -.
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.
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)
Plus simple:
export
à toutes les ligneseval
le touteval $(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
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}"
}
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
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
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
Mes exigences étaient:
export
(pour la compatibilité avec dotenv)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
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
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.
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 :)
J'ai des problèmes avec les solutions suggérées précédemment:
$()
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)
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:
Je suis tombé sur ce fil lorsque j'essayais de réutiliser Docker --env-file
s 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
FOO
nu)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