Ich zakres zależy od procesu
Inni respondenci pomogli mi zrozumieć, że zakres zmiennych powłoki dotyczy procesów i ich potomków .
Kiedy wpiszesz polecenie jak ls
w wierszu poleceń, faktycznie uruchamiasz proces uruchamiania ls
programu. Nowy proces ma powłokę jako swojego rodzica.
Każdy proces może mieć własne zmienne „lokalne”, które nie są przekazywane do procesów potomnych. Może również ustawiać zmienne „środowiskowe”, które są. Używanie export
tworzy zmienną środowiskową. W obu przypadkach niepowiązane procesy (równorzędne oryginału) nie zobaczą zmiennej; kontrolujemy tylko to, co widzą procesy potomne.
Załóżmy, że masz powłokę bash, którą nazwiemy A. Wpisujesz bash
, która tworzy potomną powłokę bash procesu, którą nazwiemy B. Wszystko, co wywołałeś export
w A, nadal będzie ustawione w B.
Teraz w B mówisz FOO=b
. Stanie się jedna z dwóch rzeczy:
- Jeśli B nie otrzyma (od A) zmiennej środowiskowej o nazwie
FOO
, utworzy zmienną lokalną. Dzieci B nie otrzymają go (chyba że dzwoni B export
).
- Jeśli B nie otrzyma (od a) zatytułowany jako zmienna środowiskowa
FOO
, będzie zmodyfikować go do siebie i swoich następnie rozdwojonych dzieci . Dzieci B zobaczą wartość przypisaną przez B. Nie wpłynie to jednak wcale na A.
Oto szybkie 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'
Wszystko to wyjaśnia mój pierwotny problem: ustawiłem GEM_HOME
w swojej powłoce, ale kiedy zadzwoniłem bundle install
, stworzyłem proces potomny. Ponieważ nie użyłem export
, proces potomny nie otrzymał powłoki GEM_HOME
.
Cofnięcie eksportu
Możesz „cofnąć eksport” zmiennej - zapobiegając jej przekazywaniu do dzieci - za pomocą 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
, ustawia wartość dla bieżącego procesu powłoki. Jeśli następnie uruchomię program podobny do (bundle install
), tworzy to proces potomny, do którego nie ma dostępuFOO
. Ale gdybym powiedziałexport FOO=bar
, proces potomny (i jego potomkowie) mieliby do niego dostęp. Jeden z nich mógłby z kolei wezwaćexport FOO=buzz
do zmiany wartości swoich potomków lub po prostuFOO=buzz
do zmiany wartości tylko dla siebie. Czy to w porządku?