Linux

Определение переменной с экспортом или без него

Для чего используется ключевое слово export?

В чем разница между:

export name=value

и

name=value

 

Ответ 1

Export делает переменную доступной для подпроцессов.

То есть,

export name=value

означает, что имя переменной доступно любому процессу, запущенному из этой оболочки. Если вы хотите, чтобы процесс использовал эту переменную, используйте export и запустите процесс из этой оболочки.

name=value

означает, что область видимости переменной ограничена оболочкой и недоступна для любого другого процесса. Это можно использовать, например, для переменных цикла, временных переменных и т.д. Важно отметить, что экспорт переменной не делает ее доступной для родительских процессов. То есть, указание и экспорт переменной в порожденном процессе не делает ее доступной в процессе, который ее запустил.

 

Ответ 2

Другие ответили, что экспорт делает переменную доступной для вложенных оболочек, и это верно, но является лишь побочным эффектом. Когда вы экспортируете переменную, она помещается в окружение текущей оболочки (то есть оболочка вызывает putenv(3) или setenv(3)).

Окружение процесса наследуется через exec, что делает переменную видимой во вложенных оболочках. Цель 'export' - заставить переменные «быть в окружении последующих выполняемых команд», независимо от того, являются ли эти команды подоболочками или подпроцессами. Наивной реализацией было бы просто поместить переменную в окружение оболочки, но это сделало бы невозможной реализацию export -p.

 

Ответ 3

Бытует мнение, что при порождении подоболочек не обязательно экспортировать в bash, в то время как другие утверждают прямо противоположное. Важно отметить разницу между подоболочками (те, которые создаются с помощью «()», «’’», «$()» или циклов) и подпроцессами (процессы, которые вызываются по имени, например, литерал bash, появляющийся в вашем скрипте). Подоболочки будут иметь доступ ко всем переменным родителя, независимо от их экспортированного состояния. Подпроцессы будут видеть только экспортированные переменные. Общим в этих двух конструкциях является то, что ни одна из них не может передавать переменные обратно родительской оболочке.

$ noexport=noexport; export export=export; (echo subshell: $noexport $export; subshell=subshell); bash -c 'echo subprocess: $noexport $export; subprocess=subprocess'; echo parent: $subshell $subprocess

subshell: noexport export

subprocess: export

parent:

Есть еще один источник путаницы: некоторые думают, что «форкнутые» подпроцессы это те, которые не видят неэкспортированных переменных. Обычно за fork() сразу следуют exec(), поэтому кажется, что искать нужно именно fork(), а на самом деле это exec(). Вы можете запускать команды без fork() сначала с помощью команды exec, и процессы, запущенные этим методом, также не будут иметь доступа к неэкспортированным переменным:

$ noexport=noexport; export export=export; exec bash -c 'echo execd process: $noexport $export; execd=execd'; echo parent: $execd

execd process: export

Обратите внимание, что на этот раз мы не видим строки parent:, потому что мы заменили родительскую оболочку командой exec, поэтому для выполнения этой команды ничего не надо.

 

Ответ 4

export NAME=value для настроек и переменных, которые имеют значение для подпроцесса.

NAME=value для временных переменных или переменных цикла, частных для текущего процесса оболочки.

Более подробно export  отмечает имя переменной в среде, которая копируется в подпроцессы и их подпроцессы при создании. Ни имя, ни значение никогда не копируются из подпроцесса.

  • Распространенная ошибка - ставить пробел вокруг знака равенства:

$ export FOO = "bar"  

bash: export: '=': неправильный идентификатор

  • Подпроцесс видит только экспортированную переменную:

$ A="Alice"; export B="Bob"; echo "echo A is \$A. B is \$B" | bash

A is . B is Bob

  • Изменения в подпроцессе не изменяют основную оболочку:

$ export B="Bob"; echo 'B="Banana"' | bash; echo $B

Bob

  • Переменные, отмеченные для экспорта, имеют значения, скопированные при создании подпроцесса:

$ export B="Bob"; echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash &

[1] 3306

$ B="Banana"; echo '(sleep 30; echo "Subprocess 2 has B=$B")' | bash 

Subprocess 1 has B=Bob

Subprocess 2 has B=Banana

[1]+  Done         echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash

  • Только экспортированные переменные становятся частью окружения ( man environ):

$ ALICE="Alice"; export BOB="Bob"; env | grep "ALICE\|BOB"

BOB=Bob

 

Ответ 5

Как вы, возможно, уже знаете, UNIX позволяет процессам иметь набор переменных среды, которые представляют собой пары ключ/значение, причем ключ и значение являются строками. Операционная система отвечает за сохранение этих пар для каждого процесса отдельно.

Программа может получить доступ к своим переменным среды через этот UNIX API:

  • char *getenv(const char *name);

  • int setenv(const char *name, const char *value, int override);

  • int unsetenv(const char *name);

 

Процессы также наследуют переменные среды от родительских процессов. Операционная система отвечает за создание копии всех "envar" в момент создания дочернего процесса.

Bash , среди других оболочек, может устанавливать свои переменные среды по запросу пользователя. Это то,  для чего export существует.

Export- это команда Bash для установки переменной среды для Bash. Все переменные, установленные с помощью этой команды, будут унаследованы всеми процессами, создаваемыми этим Bash.

Другой вид переменной в Bash - это внутренняя переменная. Поскольку Bash - это не просто интерактивная оболочка, это фактически интерпретатор сценариев, так как он, как и любой другой интерпретатор (например, Python), может хранить свой собственный набор переменных. Следует отметить, что Bash (в отличие от Python) поддерживает только строковые переменные.

Обозначение для определения переменных Bash - name=value. Эти переменные остаются внутри Bash и не имеют ничего общего с переменными среды, хранящимися в операционной системе.

Также стоит отметить, что согласно справочному руководству Bash:

среда для любой простой команды или функции может быть временно расширена путем добавления к ней префиксов с назначением параметров, как описано в разделе «Параметры оболочки». Эти операторы присваивания влияют только на среду, видимую этой командой.

Подводя итог:

  • export используется для установки переменной окружения в операционной системе. Эта переменная будет доступна всем дочерним процессам, созданным текущим процессом Bash.

  • Обозначение переменной Bash (имя = значение) используется для установки локальных переменных, доступных только для текущего процесса bash.

  • Обозначение переменной Bash перед другой командой создает переменную среды только для области действия этой команды.

 

Ответ 6

Вот еще один пример:

VARTEST="value of VARTEST" 

#export VARTEST="value of VARTEST" 

sudo env | grep -i vartest 

sudo echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}" 

sudo bash -c 'echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}"'  

Только при использовании экспорта VARTEST значение VARTEST доступно в sudo bash -c '...'!

 

Схожие статьи

Linux

Как получить информацию о только что запущенном процессе

Linux

Как мне запросить ввод Да/Нет/Отмена в сценарии оболочки Linux

Linux

Как сделать так, чтобы дочерний процесс завершался после завершения родительского

REOS. Игровой Linux
Linux

REOS. Игровой Linux