Eles têm escopo definido pelo processo
Os outros respondedores me ajudaram a entender que o escopo da variável shell é sobre processos e seus descendentes .
Quando você digita um comando como ls
na linha de comando, você está realmente bifurcação um processo para executar o ls
programa. O novo processo tem seu shell como pai.
Qualquer processo pode ter suas próprias variáveis "locais", que não são passadas para processos filho. Também pode definir variáveis de "ambiente", quais são. Usar export
cria uma variável de ambiente. Em ambos os casos, processos não relacionados (pares do original) não verão a variável; estamos apenas controlando o que os processos filhos veem.
Suponha que você tenha um shell bash, que chamaremos de A. Você digita bash
, que cria um shell bash do processo filho, que chamaremos de B. Qualquer coisa que você chamou export
em A ainda será definida em B.
Agora, em B, você diz FOO=b
. Uma de duas coisas acontecerá:
- Se B não recebeu (de A) uma variável de ambiente chamada
FOO
, ela criará uma variável local. Filhos de B não o receberão (a menos que B ligue export
).
- Se B se receber (de A) uma variável de ambiente callled
FOO
, ele irá modificá-lo para si e seus filhos posteriormente bifurcados . Filhos de B verão o valor que B atribuiu. No entanto, isso não afetará A.
Aqui está uma demonstração rápida.
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'
Tudo isso explica meu problema original: coloquei GEM_HOME
no meu shell, mas quando liguei bundle install
, isso criou um processo filho. Por não ter usado export
, o processo filho não recebeu o shell GEM_HOME
.
Não exportando
Você pode "cancelar a exportação" de uma variável - impedindo que ela seja passada para crianças - usando 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
, isso define o valor do processo atual do shell. Se eu executar um programa como (bundle install
), que cria um processo filho, ao qual não há acessoFOO
. Mas se eu tivesse ditoexport FOO=bar
, o processo filho (e seus descendentes) teria acesso a ele. Um deles poderia, por sua vez, pedirexport FOO=buzz
para alterar o valor de seus descendentes, ou apenasFOO=buzz
alterar o valor apenas para si. Isso é certo?