Для чего export
?
В чем разница между:
export name=value
а также
name=value
Для чего export
?
В чем разница между:
export name=value
а также
name=value
Ответы:
export
делает переменную доступной для подпроцессов.
Это,
export name=value
означает, что имя переменной доступно любому процессу, который вы запускаете из этого процесса оболочки. Если вы хотите, чтобы процесс использовал эту переменную, используйте export
и запустите процесс из этой оболочки.
name=value
означает, что область действия переменной ограничена оболочкой и недоступна для любого другого процесса. Вы бы использовали это для (скажем) переменных цикла, временных переменных и т. Д.
Важно отметить, что экспорт переменной не делает ее доступной для родительских процессов. То есть, указание и экспорт переменной в порожденном процессе не делает ее доступной в процессе, который ее запустил.
name=value command
делает переменную доступной в подпроцессе command
.
Другие ответили, что экспорт делает переменную доступной для подоболочек, и это правильно, но это просто побочный эффект. Когда вы экспортируете переменную, она помещает эту переменную в среду текущей оболочки (то есть оболочка вызывает putenv(3)
или setenv(3)
).
Среда процесса наследуется через exec, делая переменную видимой в подоболочках.
Изменить (с перспективой на 5 лет): это глупый ответ. Цель «экспорта» состоит в том, чтобы сделать переменные «находящимися в среде последовательно выполняемых команд», независимо от того, являются ли эти команды подоболочками или подпроцессами. Наивной реализацией было бы просто поместить переменную в среду оболочки, но это сделало бы невозможной реализацию export -p
.
bash
, export действительно добавляет переменную в среду текущей оболочки, но это не так dash
. Мне кажется, что добавление переменной в среду текущей оболочки является самым простым способом реализации семантики export
, но такое поведение не является обязательным.
dash
с этим связано. Оригинальный постер спрашивал конкретно о bash
.
bash
но в равной степени относится к любому варианту оболочки Борна. Быть слишком конкретным и давать ответы, относящиеся только к bash
делу, - великое зло.
bash
это jQuery оболочки.
export makes the variable available to subshells, and that is correct
Это очень запутанное использование терминологии. Подоболочкам не нужно export
наследовать переменные. Подпроцессы делают.
Было сказано, что нет необходимости экспортировать в 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
команду, поэтому для выполнения этой команды больше ничего не осталось.
&
) также создает подоболочку.
var=asdf bash -c 'echo $var'
или var=asdf exec bash -c 'echo $var'
? Выход есть asdf
. Это ;
имеет значение, если поместить после определения переменной. Каково было бы объяснение? Похоже, что var
(без ;
) отношение к порожденному подпроцессу как-то связано с тем, что оболочка origin не имеет к этому никакого отношения echo $var
ничего не печатает, если выполняется во второй строке. Но одна подкладка var=asdf bash -c 'echo $var'; echo $var
дает asdf\nasdf
.
export NAME=value
для настроек и переменных, которые имеют значение для подпроцесса.
NAME=value
для временных или петлевых переменных, приватных для текущего процесса оболочки.
Более подробно export
помечает имя переменной в среде, которая копирует подпроцессы и их подпроцессы при создании. Ни одно имя или значение никогда не копируются из подпроцесса.
Распространенной ошибкой является размещение пробела вокруг знака равенства:
$ export FOO = "bar"
bash: export: `=': not a valid identifier
Подпроцесс B
видит только экспортированную переменную ( ):
$ 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
Итак, теперь это должно быть так же ясно, как летнее солнце! Спасибо Брэйну Агнью, Александру и Уильяму Пруселлу.
Следует отметить, что вы можете экспортировать переменную, а затем изменить значение. Измененное значение переменной будет доступно дочерним процессам. Как только экспорт был установлен для переменной, вы должны сделать, export -n <var>
чтобы удалить свойство.
$ K=1
$ export K
$ K=2
$ bash -c 'echo ${K-unset}'
2
$ export -n K
$ bash -c 'echo ${K-unset}'
unset
Как вы, возможно, уже знаете, UNIX позволяет процессам иметь набор переменных среды, которые представляют собой пары ключ / значение, причем ключ и значение являются строками. Операционная система отвечает за хранение этих пар для каждого процесса в отдельности.
Программа может получить доступ к своим переменным среды через этот UNIX API:
char *getenv(const char *name);
int setenv(const char *name, const char *value, int override);
int unsetenv(const char *name);
Процессы также наследуют переменные среды от родительских процессов. Операционная система отвечает за создание копии всех «envars» в момент создания дочернего процесса.
Bash , помимо других оболочек, способен устанавливать переменные окружения по запросу пользователя. Это то, export
для чего существует.
export
команда Bash для установки переменной окружения для Bash Все переменные, установленные с помощью этой команды, будут наследоваться всеми процессами, которые создаст этот Bash.
Больше на Окружающей среде в Баше
Другой тип переменной в Bash - это внутренняя переменная. Поскольку Bash - это не просто интерактивная оболочка, это фактически интерпретатор сценариев, как и любой другой интерпретатор (например, Python), он может хранить свой собственный набор переменных. Следует отметить, что Bash (в отличие от Python) поддерживает только строковые переменные.
Обозначение для определения переменных Bash является name=value
. Эти переменные остаются внутри Bash и не имеют ничего общего с переменными среды, которые хранятся в операционной системе.
Подробнее о параметрах оболочки (включая переменные)
Также стоит отметить, что, согласно справочнику Bash:
Среду для любой простой команды или функции можно временно дополнить, добавив к ней префиксы с помощью параметров, как описано в разделе Параметры оболочки . Эти операторы присваивания влияют только на среду, видимую этой командой.
Подводя итог:
export
используется для установки переменной среды в операционной системе. Эта переменная будет доступна всем дочерним процессам, созданным текущим процессом Bash.Общепринятый ответ подразумевает это, но я хотел бы сделать явное соединение оболочки встроенных команд:
Как уже упоминалось, export
сделает переменную доступной как для оболочки, так и для дочерних элементов. Если export
это не используется, то переменная будет доступна только в оболочке, и только оболочка встроенные команды могут получить к нему доступ.
Это,
tango=3
env | grep tango # prints nothing, since env is a child process
set | grep tango # prints tango=3 - "type set" shows `set` is a shell builtin
Вот еще один пример:
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}"'
Только с помощью export VARTEST значение VARTEST доступно в sudo bash -c '...'!
Для дальнейших примеров см .:
bash-hackers.org/wiki/doku.php/scripting/processtree
Просто чтобы показать разницу между экспортируемой переменной, находящейся в среде (env), и неэкспортированной переменной, не находящейся в среде:
Если я сделаю это:
$ MYNAME=Fred
$ export OURNAME=Jim
тогда в env появляется только $ OURNAME. Переменная $ MYNAME отсутствует в env.
$ env | grep NAME
OURNAME=Jim
но переменная $ MYNAME существует в оболочке
$ echo $MYNAME
Fred
Два из создателей UNIX, Брайан Керниган и Роб Пайк, объясняют это в своей книге «Среда программирования UNIX». Google для названия, и вы легко найдете PDF-версию.
Они обращаются к переменным оболочки в разделе 3.6 и фокусируются на использовании export
команды в конце этого раздела:
Если вы хотите, чтобы значение переменной было доступно в подоболочках, следует использовать команду экспорта оболочки. (Вы можете подумать, почему нет способа экспортировать значение переменной из вложенной оболочки в ее родительский объект).
Хотя это явно не упоминается в обсуждении, НЕ обязательно использовать экспорт при порождении подоболочки изнутри bash, поскольку все переменные копируются в дочерний процесс.
export name=value
это не портативно. В зависимости от того, что именно вы хотите, попробуйтеname=value; export name
портативное решение.