Esportare una variabile env per renderla disponibile in tutte le sotto shell e possibile modificarla?


22

Supponiamo di averlo fatto

export MY_VAR=0

in ~/.bashrc.

Ho un terminale gnome aperto e in questo terminale cambio $MY_VARvalore in 200. Quindi, se lo faccio

echo $MY_VAR

in questo terminale, 200viene mostrato.

Ora, ho aperto un'altra scheda nel mio terminale GNOME, e lo faccio

echo $MY_VAR

... e invece 200che ho 0.

Cosa devo fare per mantenere il valore 200 quando un terminale modifica una variabile d'ambiente, rendendo questa modifica (impostata su 200) disponibile per tutte le successive sub shell e simili? È possibile?

Risposte:


23

Una copia dell'ambiente si propaga alle sotto shell, quindi funziona:

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

ma dal momento che è una copia, non puoi ottenere quel valore fino alla shell genitore, non cambiando l'ambiente, almeno.

Sembra che tu voglia davvero fare un passo avanti, ovvero creare qualcosa che si comporta come una variabile globale, condivisa da shell "fratelli" avviate separatamente dal genitore - come la tua nuova scheda in Gnome Terminal.

Principalmente, la risposta è "impossibile, perché le variabili di ambiente non funzionano in questo modo". Tuttavia, c'è un'altra risposta, che è, beh, puoi sempre hackerare qualcosa. Un approccio sarebbe quello di scrivere il valore della variabile in un file, come ~/.myvar, e quindi includerlo in ~/.bashrc. Quindi, ogni nuova shell inizierà con il valore letto da quel file.

È possibile fare un ulteriore passo avanti: ~/.myvaressere nel formato MYVAR=200e quindi impostare PROMPT_COMMAND=source ~/.myvar, il che farebbe rileggere il valore ogni volta che si riceve un nuovo prompt. Non è ancora del tutto una variabile globale condivisa, ma sta cominciando ad agire come esso. Non si attiverà fino a quando non verrà visualizzato un prompt, che a seconda di ciò che si sta tentando di fare potrebbe essere una grave limitazione.

E poi, ovviamente, la prossima cosa è scrivere automaticamente le modifiche ~/.myvar. Questo diventa un po 'più complicato, e mi fermerò a questo punto, perché in realtà le variabili di ambiente non erano pensate per essere un meccanismo di comunicazione tra shell, ed è meglio trovare solo un altro modo per farlo.


10
Riesco a sentire il guscio che strilla sotto la tortura

Si scusa. Ecco perché mi sono fermato. :)
mattdm,

"che è fare qualcosa che si comporta come una variabile globale" - Beh, in effetti, è quello che stavo cercando di realizzare. ~ / .Myvar non è carino, ma funziona. Hai un altro suggerimento?
Qualcuno usa ancora il tuo MS-DOS il

2
Bene, facciamo un passo indietro. Perché vuoi una variabile globale?
Mattdm,

1
@mattdm: ho alcune "burocrazie" alle quali devo obbedire. Uno di questi è un mucchio di codici che devo impegnare insieme a un commento. Questi codici si trovano ora in una gerarchia di cartelle (home / utente / progetti / projectcode / code1 / code2). Ho creato una funzione che estrae code1 e code2 per invogliare (quindi quando ho bisogno di fare un'attività, chiamo semplicemente la funzione all'interno della directory con i codici) e loro, quando commetto, uso vim e ci sono alcune funzioni che leggi questi var e inserisci un commento automaticamente. Penso che usare i file per quello possa essere una soluzione.
Qualcuno usa ancora il tuo MS-DOS il

13

Supponiamo che io sono export MY_VAR=0in ~/.bashrc.

Questo è il tuo errore proprio lì. È necessario definire le variabili di ambiente in ~/.profile, che vengono lette quando si accede. ~/.bashrcViene letto ogni volta che si avvia una shell; quando si avvia il guscio interno, ha la precedenza MY_VAR. Se non lo avessi fatto, la tua variabile d'ambiente si sarebbe propagata verso il basso.

Per ulteriori informazioni su ~/.bashrcvs ~/.profile, vedere i miei post precedenti su questo argomento .

Si noti che la propagazione verso l'alto (ottenere un valore modificato dalla subshell riflessa automaticamente nella shell padre) non è possibile, punto e basta.



3

Non usare affatto variabili d'ambiente. Usa i file.

Per evitare che i processi si calpestino l'un l'altro durante l'aggiornamento / la lettura del file, utilizzare file di blocco e script di aggiornamento front-end di piccole dimensioni il cui scopo è semplicemente aggiornare un file con $ 1 se non è bloccato. I lockfile vengono implementati controllando sostanzialmente se esiste un file specifico (/var/run/yourscript.lck) e, in tal caso, attendi che il file scompaia per un po 'e fallisca se non lo fa. Inoltre, è necessario eliminare il file di blocco al termine dell'aggiornamento del file.

Preparati a gestire una situazione in cui uno script non può aggiornare un file perché il file è occupato.


8
Un trucco: usa le directory invece dei file per bloccare, perché mkdirfunziona come un test atomico e crea.
Mattdm,

1
Se volete parlare di blocco, potreste anche usareflock(2)
Ehtesh Choudhury,

@mattdm Ho scoperto che anche un collegamento simbolico ln -s dummy lockfile(anche se interrotto) potrebbe non funzionare se il collegamento simbolico esiste già. Mi chiedo un modo per testare se è veramente sicuro al 100%.
Aquarius Power il

1

Quando ho appena cercato su Google questa domanda, stavo cercando di risolvere il problema di aggiornare lo stato (cioè le variabili della shell) da un sottotitolo. In modo che si possano assegnare variabili, diciamo, all'interno di una pipeline - e l'assegnazione sarebbe chiaramente visibile al genitore.

Ovviamente, ciò non è possibile in modo semplice perché le singole parti di una pipeline vengono eseguite in subshells, che sono fork"elaborate dalla shell genitore e quindi hanno memoria che è vista copia su scrittura nella memoria del genitore. Tuttavia, supponevo che una soluzione snella e trasparente potesse essere possibile basata su una sorta di IPC "a memoria condivisa " .

E ho anche trovato un'implementazione esattamente di questo disegno ... ma è in Perl.

Aggiungendo comunque questa risposta come possibile soluzione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.