Они ограничены процессом
Другие ответчики помогли мне понять, что область видимости переменных оболочки - это процессы и их потомки .
Когда вы набираете команду, как 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изменить значение только для себя. Это примерно так?