web-dev-qa-db-fra.com

Exporter une variable env être disponible à tous les sous-coquilles et éventuellement être modifié?

Supposons que j'ai

export MY_VAR=0

dans ~/.bashrc.

J'ai un terminal gnome ouvert et dans ce terminal, je change $MY_VAR valeur à 200. Donc, si je fais

echo $MY_VAR

dans ce terminal, 200 est montré.

Maintenant, j'ai ouvert un autre onglet dans mon terminal Gnome et faire

echo $MY_VAR

... et au lieu de 200, J'ai 0.

Que dois-je faire pour persister la valeur de 200 lorsqu'un terminal modifie une variable d'environnement, ce qui rend cette modification (réglage à 200) disponible pour toutes les sous-coquilles ultérieures et telle? Est-ce possible?

A copie de l'environnement se propage aux sous-coquilles, de sorte que cela fonctionne:

$ export MY_VAR=200
$ bash
$ echo $MY_VAR
200

mais comme il s'agit d'une copie, vous ne pouvez pas obtenir cette valeur jusqu'à la coquille mère - non pas en modifiant l'environnement, au moins.

On dirait que vous voulez réellement aller un pas plus loin, ce qui consiste à faire quelque chose qui agit comme une variable globale, partagée par des coquillages "frères de sœurs" initiés séparément du parent - comme votre nouvel onglet dans le terminal Gnome.

Surtout, la réponse est "Vous ne pouvez pas, car les variables d'environnement ne fonctionnent pas de cette façon". Cependant, il y a une autre réponse, ce qui est bien, vous pouvez toujours pirater quelque chose. Une approche serait d'écrire la valeur de la variable à un fichier, comme ~/.myvar, puis inclure cela dans ~/.bashrc. Ensuite, chaque nouvelle coque sera Démarrer avec la valeur lue de ce fichier.

Vous pourriez aller plus loin - faites ~/.myvar être dans le format MYVAR=200, puis défini Prompt_COMMAND=source ~/.myvar, qui causerait la valeur de la valeur à chaque fois que vous obtenez une nouvelle invite. Ce n'est toujours pas tout à fait une variable globale partagée, mais il commence à agir comme celui-ci. Il ne s'activera pas tant qu'une invite revient, cependant, selon laquelle vous essayez de faire pourrait être une grave limitation.

Et puis, bien sûr, la prochaine chose est de écrire Changements à ~/.myvar. Cela devient un peu plus compliqué, et je vais m'arrêter à ce stade, car de manière réelle, les variables d'environnement n'étaient pas censées être un mécanisme de communication inter-shell, et il vaut mieux trouver une autre façon de le faire.

23
mattdm

Supposons que j'ai export MY_VAR=0 dans ~/.bashrc.

C'est votre erreur là-bas. Vous devez définir vos variables d'environnement dans ~/.profile, qui est lu lorsque vous vous connectez. ~/.bashrc est lu chaque fois que vous démarrez une coquille; Lorsque vous démarrez la coque intérieure, il remplace MY_VAR. Si vous n'aviez pas fait cela, votre variable d'environnement se propagerait vers le bas.

Pour plus d'informations sur ~/.bashrc vs ~/.profile, voir mon précédentPostsONCecisujet .

Notez que La propagation ascendante (obtenir une valeur modifiée du sous-groupe reflétée automatiquement dans la coque mère) n'est pas possible, arrêt complet.

La coquille de poisson peut faire cela avec:

set -U MY_VAR 0

(Voir http://fishshell.com/docs/current/commands.html#set )

Pour exécuter une commande de poisson d'une autre coquille, vous pouvez exécuter fish -c, par exemple. :

fish -c "set -u MY_VAR 0"
4
Rickard von Essen

N'utilisez pas du tout des variables d'environnement. Utilisez des fichiers.

Pour empêcher les processus de se passer de l'autre lors de la mise à jour/de la lecture du fichier, utilisez LockFiles et de petits scripts de mise à jour frontaux dont le but est de mettre à jour un fichier avec 1 $ s'il n'est pas verrouillé. LockFiles sont implémentés en vérifiant essentiellement si un fichier spécifique existe (/var/run/yourscript.lck) et, si tel est le cas, attendez que le fichier disparaisse pendant un moment et échouez si cela ne le fait pas. Vous devez également supprimer le fichier Lockfile lors de la mise à jour du fichier.

Soyez prêt à gérer une situation dans laquelle un script ne peut pas mettre à jour un fichier car le fichier est occupé.

3
LawrenceC

Lorsque je viens de googler cette question, j'essayais de résoudre le problème de la mise à jour de l'état (c'est-à-dire des variables de shell) à partir de sous-vases. Pour que l'on puisse attribuer des variables, par exemple, à l'intérieur d'un pipeline - et l'affectation serait visible de manière transparente au parent.

Bien sûr, cela n'est pas possible de manière simple car les parties individuelles d'un pipeline sont exécutées dans des sous-espions, qui sont fork 'ED de la coque mère et ont donc une mémoire qui est Copie-on-écriture Afficher sur la mémoire du parent. Cependant, je suppose que la solution mince et transparente pourrait être possible sur la base de la mémoire partagée " " sorte de IPCS .

Et j'ai même trouvé une implémentation de cette conception exactement ... mais c'est à Perl.

Ajout de cette réponse quand même comme solution possible.

1
ulidtko