Они ограничены процессом
Другие ответчики помогли мне понять, что область видимости переменных оболочки - это процессы и их потомки .
Когда вы набираете команду, как ls
в командной строке, вы фактически разветвляете процесс для запуска ls
программы. Новый процесс имеет вашу оболочку в качестве родителя.
Любой процесс может иметь свои собственные «локальные» переменные, которые не передаются дочерним процессам. Он также может устанавливать переменные окружения, которые есть. Использование export
создает переменную среды. В любом случае несвязанные процессы (одноранговые узлы оригинала) не увидят переменную; мы контролируем только то, что видят дочерние процессы.
Предположим, у вас есть оболочка bash, которую мы будем называть A. Вы вводите bash
, которая создает дочернюю оболочку bash процесса, которую мы будем называть B. Все, что вы вызываете export
в A, все равно будет установлено в B.
Теперь, в B, вы говорите FOO=b
. Произойдет одно из двух:
- Если B не получил (от A) переменную среды, вызванную
FOO
, он создаст локальную переменную. Дети Б не получат его (если Б не звонит export
).
- Если B действительно получил (от A) переменную окружения
FOO
, вызванную , он изменит ее для себя и своих потомков-потомков . Дети B увидят значение, присвоенное B. Однако это никак не повлияет на А.
Вот быстрое демо.
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'
Все это объясняет мою первоначальную проблему: я установил GEM_HOME
в своей оболочке, но когда я позвонил bundle install
, это создало дочерний процесс. Поскольку я не использовал export
, дочерний процесс не получил оболочки GEM_HOME
.
Un-экспорт
Вы можете «отменить экспорт» переменной - предотвратить ее передачу дочерним элементам - используя 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
, это устанавливает значение для текущего процесса оболочки. Если я затем запускаю программу наподобие (bundle install
), она создает дочерний процесс, к которому нет доступаFOO
. Но если бы я сказалexport FOO=bar
, дочерний процесс (и его потомки) имели бы к нему доступ. Один из них может, в свою очередь, вызватьexport FOO=buzz
изменение значения для его потомков или простоFOO=buzz
изменить значение только для себя. Это примерно так?