Puis-je exporter une variable vers l'environnement à partir d'un script bash sans la sourcer?

282

Supposons que j'ai ce script

export.bash :

#! /usr/bin/env bash
export VAR="HELLO, VARIABLE"

Lorsque j'exécute le script et que j'essaie d'accéder à $VAR, je n'obtiens aucune valeur!

echo $VAR

Existe-t-il un moyen d'accéder au fichier en$VAR exécutant simplement export.bash sans le sourcer?

tarrsalah
la source
1
Vous pouvez essayer d'utiliser un alias au lieu d'un script pour définir votre variable.
jdigital
Le script sur lequel je travaille, est une sorte de gestionnaire virtuel java, je fais du calcul puis je devrais exporter un $ JAVA_HOME vers l'env, et l'ajouter à PATH.
tarrsalah
Eh bien, vous pouvez écrire les informations dans un fichier, puis les relire, mais l'approvisionnement semble beaucoup plus facile.
jdigital
7
les processus enfants ne peuvent pas modifier l'environnement de leurs parents. Le parent doit choisir de se modifier (avec sourceou evalou ...)
glenn jackman
1
Pour en savoir plus sur la source, man sourcene fonctionnera pas car sourceest intégré à bash, vous devez exécuterhelp source
peterchaula

Réponses:

319

Existe-t-il un moyen d'accéder à l ' $VARen l'exécutant simplement export.bashsans l'approvisionner?

Réponse rapide: Non.

Mais il existe plusieurs solutions possibles.

Le plus évident, que vous avez déjà mentionné, est d'utiliser sourceou .d'exécuter le script dans le contexte du shell appelant:

$ cat set-vars1.sh 
export FOO=BAR
$ . set-vars1.sh 
$ echo $FOO
BAR

Une autre façon consiste à avoir le script, plutôt que de définir une variable d'environnement, imprimer des commandes qui définiront la variable d'environnement:

$ cat set-vars2.sh
#!/bin/bash
echo export FOO=BAR
$ eval "$(./set-vars2.sh)"
$ echo "$FOO"
BAR

Une troisième approche consiste à avoir un script qui définit vos variables d'environnement en interne, puis invoque une commande spécifiée avec cet environnement:

$ cat set-vars3.sh
#!/bin/bash
export FOO=BAR
exec "$@"
$ ./set-vars3.sh printenv | grep FOO
FOO=BAR

Cette dernière approche peut être très utile, bien qu'elle ne soit pas pratique pour une utilisation interactive car elle ne vous donne pas les paramètres de votre shell actuel (avec tous les autres paramètres et l'historique que vous avez créés).

Keith Thompson
la source
57

Afin d'exporter la variable VAR en premier, la façon la plus logique et qui semble la plus efficace consiste à rechercher la variable:

. ./export.bash

ou

source ./export.bash

Maintenant, en écho depuis le shell principal, cela fonctionne

 echo $VAR
HELLO, VARABLE

Nous allons maintenant réinitialiser VAR

export VAR=""
echo $VAR

Nous allons maintenant exécuter un script pour générer la variable, puis la désactiver:

./test-export.sh 
HELLO, VARABLE
--
.

le code: cat test-export.sh

    #!/bin/bash
    # Source env variable
    source ./export.bash

    # echo out the variable in test script
    echo $VAR

    # unset the variable 
    unset VAR
    # echo a few dotted lines
    echo "---"
    # now return VAR which is blank
    echo $VAR

Voici une façon

S'IL VOUS PLAÎT NOTE: Les exportations sont limitées au script qui exécute les exportations dans votre console principale - pour autant qu'un travail cron je l'ajouterais comme la console comme ci-dessous ... pour la partie commande encore discutable: voici comment vous feriez courir depuis votre shell:

Sur votre invite de commande (tant que l'export.bash a plusieurs valeurs d'écho)

IFS=$'\n'; for entries in $(./export.bash); do  export $entries;  done; ./v1.sh 
HELLO THERE
HI THERE

chat v1.sh

#!/bin/bash
echo $VAR
echo $VAR1

Maintenant, tant que c'est pour votre usage - vous pouvez rendre les variables disponibles pour vos scripts à tout moment en faisant un alias bash comme ceci:

myvars ./v1.sh
HELLO THERE
HI THERE

echo $VAR

.

ajoutez ceci à votre .bashrc

function myvars() { 
    IFS=$'\n'; 
    for entries in $(./export.bash); do  export $entries;  done; 

    "$@"; 

    for entries in $(./export.bash); do variable=$(echo $entries|awk -F"=" '{print $1}'); unset $variable;
done

}

sourcez votre fichier bashrc et vous pouvez faire comme ci-dessus à tout moment ...

Quoi qu'il en soit, revenons au reste ..

Cela l'a rendu disponible globalement puis a exécuté le script.

il suffit de l'écho, puis d'exporter sur l'écho!

chat export.bash

#!/bin/bash
echo "VAR=HELLO THERE"

Maintenant dans le script ou votre console:

 export "$(./export.bash)"

Essayer:

echo $VAR
HELLO THERE

Plusieurs valeurs tant que vous savez à quoi vous vous attendez dans un autre script en utilisant la méthode ci-dessus:

chat export.bash

#!/bin/bash
echo "VAR=HELLO THERE"
echo "VAR1=HI THERE"

cat test-export.sh

#!/bin/bash

IFS=$'\n'
for entries in $(./export.bash); do
   export $entries
done

echo "round 1"
echo $VAR
echo $VAR1

for entries in $(./export.bash); do
     variable=$(echo $entries|awk -F"=" '{print $1}');
     unset $variable
done

echo "round 2"
echo $VAR
echo $VAR1

Maintenant les résultats

 ./test-export.sh 
round 1
HELLO THERE
HI THERE
round 2


.

et la dernière mise à jour finale pour attribuer automatiquement lire les VARIABLES:

./test-export.sh 
Round 0 - Export out then find variable name - 
Set current variable to the variable exported then echo its value
$VAR has value of HELLO THERE
$VAR1 has value of HI THERE
round 1 - we know what was exported and we will echo out known variables
HELLO THERE
HI THERE
Round 2 - We will just return the variable names and unset them 
round 3 - Now we get nothing back

Le script: cat test-export.sh

#!/bin/bash

IFS=$'\n'
echo "Round 0 - Export out then find variable name - "
echo "Set current variable to the variable exported then echo its value"
for entries in $(./export.bash); do
 variable=$(echo $entries|awk -F"=" '{print $1}');
 export $entries
 eval current_variable=\$$variable
 echo "\$$variable has value of $current_variable"
done


echo "round 1 - we know what was exported and we will echo out known variables"
echo $VAR
echo $VAR1

echo "Round 2 - We will just return the variable names and unset them "
for entries in $(./export.bash); do
 variable=$(echo $entries|awk -F"=" '{print $1}');
 unset $variable
done

echo "round 3 - Now we get nothing back"
echo $VAR
echo $VAR1
VH
la source
Je veux exporter VAR en exécutant le fichier, pas en le sourcant.
tarrsalah
@vahid, vous devez expliquer ce que fait votre script.
FDinoff
1
pourquoi ne pas annuler la variable après le sourcing? ce sera beaucoup plus facile que la douleur que vous essayez de vous causer vous-même mettra à jour le script de test-export
VH
J'ai donné une autre façon de le faire Tarrsalah
VH
mises à jour finales correctes - des problèmes avec la méthode suggérée et le contournement de l'idée d'alias bashrc seraient probablement une excellente solution
VH
22

Exécuter

set -o allexport

Toutes les variables que vous sourcez à partir d'un fichier après cela seront exportées dans votre shell.

source conf-file

Lorsque vous avez terminé, exécutez. Cela désactivera le mode allexport.

set +o allexport
mdornfe1
la source
7
L'intérêt de la question est "Comment exporter sans source". Cette réponse utilise la source.
Gonen I
@ekkis Oui, cela ne répond pas exactement à la question, mais chaque fois que je cherchais sur Google comment exporter des variables à partir d'un fichier, ce sujet apparaissait. Donc je l'ai juste mis là pour moi.
mdornfe1
Simple et facile à utiliser. cela devrait être marqué comme la réponse.
QkiZ
1
J'ai voté en faveur de cela parce que l'énoncé du problème original m'a amené à comprendre que c'était ma solution fondamentale. Il y a des documents officiels sur allexport ici: gnu.org/software/bash/manual/html_node/The-Set-Builtin.html
benjaoming
ahh, +1. Cette question est le meilleur résultat de mot-clé bash source exportdans Google
ttimasdf
14

Trouvé un moyen intéressant et soigné d'exporter des variables d'environnement à partir d'un fichier:

dans env.vars:

foo=test

script de test:

eval `cat env.vars`
echo $foo         # => test
sh -c 'echo $foo' # => 

export eval `cat env.vars`
echo $foo         # => test
sh -c 'echo $foo' # => test

# a better one
export `cat env.vars`
echo $foo         # => test
sh -c 'echo $foo' # => test
Van
la source
7

Une autre solution de contournement qui, selon le cas, pourrait être utile: créer un autre bash qui hérite de la variable exportée. Il s'agit d'un cas particulier de @Keith Thompson réponse, sera tous ces inconvénients.

export.bash:

# !/bin/bash
export VAR="HELLO, VARIABLE"
bash

Maintenant:

./export.bash
echo $VAR
Gonmator
la source
Êtes-vous sûr que ce que vous avez écrit fonctionne!? Je crois que vous devez exécuter la commande de ligne:. ./export.bash
Sir Jo Black
@ Sir Jo Black, oui, bien sûr. La dernière ligne du fichier export.bash invoque en bashtant qu'enfant du shell actuel. Et depuis qu'il a VARété exporté auparavant, cette invocation inclura la variable. Bien sûr, si vous tapez, exitle VARva s'éteindre. Avez-vous vérifié?
Gonmator
D'accord! Je n'ai pas vu cette invocation ...: p
Sir Jo Black
1

La réponse est non, mais pour moi j'ai fait ce qui suit

le script: myExport

#! \bin\bash
export $1

un alias dans mon .bashrc

alias myExport='source myExport' 

Vous le sourcez toujours, mais peut-être de cette façon il est plus utilisable et il est intéressant pour quelqu'un d'autre.

Malcomar
la source
1

Vous pouvez peut-être écrire une fonction dans ~ / .zshrc, ~ / .bashrc.

# set my env
[ -s ~/.env ] && export MYENV=`cat ~/.env`
function myenv() { [[ -s ~/.env ]] && echo $argv > ~/.env && export MYENV=$argv }

En raison de l'utilisation d'une variable à l'extérieur, vous pouvez éviter d'écrire un fichier script.

zhi.yang
la source