web-dev-qa-db-fra.com

Comment écrire un script bash pour définir une variable d'environnement globale?

Récemment, j'ai écrit un script qui définit une variable d'environnement, regardez:

#!/bin/bash

echo "Pass a path:"
read path
echo $path

defaultPath=/home/$(whoami)/Desktop

if [ -n "$path" ]; then
    export my_var=$path
else
    echo "Path is empty! Exporting default path ..."
    export my_var=$defaultPath
fi

echo "Exported path: $my_var"

Cela fonctionne très bien, mais le problème est que my_var est disponible localement, je veux dire dans la fenêtre de la console où j'ai exécuté le script. 

Comment écrire un script qui me permet d’exporter la variable global environment qui peut être vue partout?

35
Katie

Chaque Shell a son propre environnement. Il n'y a pas d'environnement Universal qui apparaîtra comme par magie dans toutes les fenêtres de la console. Une variable d’environnement créée dans un Shell n’est pas accessible dans un autre Shell.

C'est encore plus restrictif. Si un shell génère un sous-shell, ce dernier a accès aux variables d'environnement du parent, mais si ce sous-shell crée une variable d'environnement, celle-ci n'est pas accessible dans le shell parent.

Si tous vos shells doivent avoir accès au même ensemble de variables, vous pouvez créer un fichier startup qui les définira à votre place. Ceci est fait dans BASH via les fichiers $HOME/.bash_profile et $HOME/.bashrc et via $HOME/.profile si $HOME/.bash_profile n'existe pas). D'autres shells ont leur propre ensemble de fichiers de démarrage. L'un est utilisé pour les connexions, et l'autre pour les obus créés sans connexions. Voir la page de manuel pour savoir exactement quels scripts de démarrage sont utilisés et dans quel ordre ils sont exécutés).

Vous pouvez essayer d’utiliser la mémoire partagée, mais je pense que cela ne fonctionne que lorsque les processus sont en cours. Même si vous trouviez un moyen de définir une partie de la mémoire partagée, elle disparaîtrait dès que cette commande est terminée. (J'ai rarement utilisé la mémoire partagée sauf pour les canaux nommés). Sinon, il n'y a vraiment aucun moyen de définir une variable d'environnement dans un Shell et de laisser un autre Shell le prendre automatiquement. Vous pouvez essayer d’utiliser named pipes ou d’écrire cette variable d’environnement dans un fichier pour que les autres shells la récupèrent.

Imaginez les problèmes qui pourraient survenir si quelqu'un pouvait changer l'environnement d'un Shell à mon insu.

35
David W.

Il suffit d’exécuter votre script Shell précédé de «.» (espace entre les points).

Cela oblige le script à exécuter les instructions dans le shell d'origine. Ainsi, les variables existent toujours après la fin du script

Ex:

cat setmyvar.sh
export myvar=exists

. ./setmyvar.sh

echo $myvar
exists
83
JDembinski

Les éléments suivants ont été extraits du deuxième paragraphe de la réponse de David W.: "Si un shell génère un sous-shell, ce sous-shell a accès aux variables d'environnement du parent, mais si ce sous-shell crée une variable d'environnement, il n'est pas accessible dans le shell principal. "

Si un utilisateur doit laisser l’enveloppe parent accéder à vos nouvelles variables d’environnement, il suffit d’exécuter la commande suivante dans l’enveloppe parent:

source <your_subshell_script>

ou en utilisant un raccourci

. <your_subshell_script>
2
Jonathan L

Vous devez ajouter la variable dans votre fichier .profile situé dans /home/$USER/.profile

Vous pouvez le faire avec cette commande:

echo 'TEST="hi"' >> $HOME/.profile

Ou bien éditez le fichier avec emacs, par exemple . Si vous voulez définir cette variable pour tous les utilisateurs, vous devez éditer/etc/profile (root)

2
MarcD

~/.bin/SOURCED/lazy script pour enregistrer et charger les données sous forme de fichiers plats pour le système. 

[ ! -d ~/.megadata ] && mkdir ~/.megadata

function save_data {
[ -z "$1" -o -z "$2" ] && echo 'save_data [:id:] [:data:]' && return
local overwrite=${3-false}
[ "$overwrite" = 'true' ] && echo "$2" > ~/.megadata/$1 && return
[ ! -f ~/.megadata/$1 ]   && echo "$2" > ~/.megadata/$1 || echo ID TAKEN set third param to true to overwrite
}

save_data computer engine
cat ~/.megadata/computer
save_data computer engine
save_data computer megaengine true

function get_data {
[ -z "$1" -o -f $1 ] && echo 'get_data [:id:]' && return


[ -f ~/.megadata/$1 ]   && cat ~/.megadata/$1 || echo ID NOT FOUND
:
}

get_data computer
get_data computer
1
Arcabard

Si vous devez définir et référencer de manière dynamique les variables d'environnement dans les scripts Shell, il convient de contourner le problème. Jugez par vous-même si cela vaut la peine d'être fait, mais le voici.

La stratégie implique d'avoir un script 'set' qui écrit dynamiquement un script 'load', qui contient du code pour définir et exporter une variable d'environnement. Le script 'load' est ensuite exécuté périodiquement par d'autres scripts qui doivent référencer la variable. BTW, la même stratégie pourrait être faite en écrivant et en lisant un fichier au lieu d’une variable.

Voici un exemple rapide ...

Set_Load_PROCESSING_SIGNAL.sh

#!/bin/bash
PROCESSING_SIGNAL_SCRIPT=./Load_PROCESSING_SIGNAL.sh
echo "#!/bin/bash" > $PROCESSING_SIGNAL_SCRIPT
echo "export PROCESSING_SIGNAL=$1" >> $PROCESSING_SIGNAL_SCRIPT
chmod ug+rwx $PROCESSING_SIGNAL_SCRIPT

Load_PROCESSING_SIGNAL.sh (il est créé dynamiquement lors de l'exécution de ce qui précède)

#!/bin/bash
export PROCESSING_SIGNAL=1

Vous pouvez tester cela avec Test_PROCESSING_SIGNAL.sh

#!/bin/bash
PROCESSING_SIGNAL_SCRIPT=./Load_PROCESSING_SIGNAL.sh
N=1
LIM=100
while [ $N -le $LIM ]
do
# DO WHATEVER LOOP PROCESSING IS NEEDED
echo "N = $N"
sleep 5
N=$(( $N + 1 ))

# CHECK PROCESSING_SIGNAL
source $PROCESSING_SIGNAL_SCRIPT
if [[ $PROCESSING_SIGNAL -eq 0 ]]; then
# Write log info indicating that the signal to stop processing was detected
# Write out all relevent info
# Send an alert email of this too
# Then exit
echo "Detected PROCESSING_SIGNAL for all stop. Exiting..."
exit 1
fi
done
1
wxwizard

Il n'y a pas vraiment d'environnement global sous UNIX.

Chaque processus a un environnement, initialement hérité du parent, mais il est local au processus après la création initiale.

Vous ne pouvez modifier que les vôtres, à moins que vous ne travailliez dans le processus avec un débogueur.

1
perh

Les variables d'environnement sont toujours "locales" pour l'exécution du processus. La commande d'exportation permet de définir des variables d'environnement pour les sous-processus. Vous pouvez consulter .bashrc pour définir des variables d’environnement au début d’un shell bash. Ce que vous essayez de faire ne semble pas possible car un processus ne peut pas modifier (ou accéder?) Aux variables d'environnement d'un autre processus.

1
Nahuel Fouilleul

Vous pouvez mettre à jour le fichier ~/.bashrc ou ~/.bash_profile utilisé pour initialiser l'environnement.

1
Jin Kim

écrivez-le dans un fichier temporaire, disons ~/.myglobalvar et lisez-le de n'importe où

echo "$myglobal" > ~/.myglobalvar
1
Sergio Abreu

Examinez le comportement de votre shell en matière de chargement (expliqué dans la page de manuel, en faisant habituellement référence à .XXXshrc ou .profile). Certains fichiers de configuration sont chargés lors de la connexion d'un shell interactif, d'autres à chaque fois que vous exécutez un shell. Placer votre variable dans cette dernière peut entraîner le comportement souhaité, par exemple. ayant toujours la variable définie en utilisant ce shell distinct (par exemple bash).

1
count0

En fait, j'ai trouvé un moyen d'y parvenir (qui dans mon cas consistait à utiliser un script bash pour définir un certain nombre d'informations d'identification de sécurité)

J'appelle simplement bash à l'intérieur du script et le shell engendré a maintenant les valeurs d'exportation

export API_USERNAME=abc
export API_PASSWORD=bbbb
bash

appeler maintenant le fichier en utilisant ~/.app-x-setup.sh me donnera un shell interactif avec la configuration de ces valeurs d’environnement

1
Dinis Cruz