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

Да или нет в сценарии Bash

Linux

OpenSuse: установка программ, правильная настройка после установки

Как установить Gnome 3, что такое графическая оболочка Gnome Shell
Linux

Как установить Gnome 3, что такое графическая оболочка Gnome Shell

Linux

Зачем нужна запись awverify CNAME для Azure?

×