Sono definiti dal processo
Gli altri risponditori mi hanno aiutato a capire che l'ambito delle variabili della shell riguarda i processi e i loro discendenti .
Quando si digita un comando come ls
nella riga di comando, in realtà si sta eseguendo un fork di un processo per eseguire il ls
programma. Il nuovo processo ha la shell come genitore.
Ogni processo può avere le sue variabili "locali", che non vengono passate ai processi figlio. Può anche impostare variabili "ambiente", che sono. L'uso export
crea una variabile d'ambiente. In entrambi i casi, i processi non correlati (peer dell'originale) non vedranno la variabile; controlliamo solo ciò che i processi figli vedono.
Supponiamo di avere una shell bash, che chiameremo A. Digiti bash
, che crea una shell bash di processo figlio, che chiameremo B. Tutto ciò che hai chiamato export
in A verrà comunque impostato in B.
Ora, in B, dici FOO=b
. Accadrà una delle due cose:
- Se B non ha ricevuto (da A) una variabile d'ambiente chiamata
FOO
, creerà una variabile locale. I bambini di B non lo riceveranno (a meno che B non chiami export
).
- Se B ha ricevuto (da A) una variabile d'ambiente chiamata
FOO
, la modificherà per sé e per i suoi figli successivamente biforcati . I figli di B vedranno il valore assegnato a B. Tuttavia, ciò non influirà affatto su A.
Ecco una breve demo.
FOO=a # set "local" environment variable
echo $FOO # 'a'
bash # forks a child process for the new shell
echo $FOO # not set
exit # return to original shell
echo $FOO # still 'a'
export FOO # make FOO an environment variable
bash # fork a new "child" shell
echo $FOO # outputs 'a'
FOO=b # modifies environment (not local) variable
bash # fork "grandchild" shell
echo $FOO # outputs 'b'
exit # back to child shell
exit # back to original shell
echo $FOO # outputs 'a'
Tutto questo spiega il mio problema originale: ho impostato GEM_HOME
nella mia shell, ma quando ho chiamato bundle install
, che ha creato un processo figlio. Poiché non avevo usato export
, il processo figlio non ha ricevuto la shell GEM_HOME
.
Un-esportazione
Puoi "annullare l'esportazione" di una variabile, impedendone il passaggio ai bambini, utilizzando export -n FOO
.
export FOO=a # Set environment variable
bash # fork a shell
echo $FOO # outputs 'a'
export -n FOO # remove environment var for children
bash # fork a shell
echo $FOO # Not set
exit # back up a level
echo $FOO # outputs 'a' - still a local variable
FOO=bar
, questo imposta il valore per l'attuale processo della shell. Se quindi eseguo un programma come (bundle install
), ciò crea un processo figlio, al quale non ho accessoFOO
. Ma se avessi dettoexport FOO=bar
, il processo figlio (e i suoi discendenti) avrebbero avuto accesso ad esso. Uno di loro potrebbe, a sua volta, chiamareexport FOO=buzz
per cambiare il valore per i suoi discendenti, o semplicementeFOO=buzz
per cambiare il valore solo per se stesso. È giusto?