Тангенциально отметим также, что export name=valueэто не портативно. В зависимости от того, что именно вы хотите, попробуйте name=value; export nameпортативное решение.
tripleee
Ответы:
1055
export делает переменную доступной для подпроцессов.
Это,
export name=value
означает, что имя переменной доступно любому процессу, который вы запускаете из этого процесса оболочки. Если вы хотите, чтобы процесс использовал эту переменную, используйте exportи запустите процесс из этой оболочки.
name=value
означает, что область действия переменной ограничена оболочкой и недоступна для любого другого процесса. Вы бы использовали это для (скажем) переменных цикла, временных переменных и т. Д.
Важно отметить, что экспорт переменной не делает ее доступной для родительских процессов. То есть, указание и экспорт переменной в порожденном процессе не делает ее доступной в процессе, который ее запустил.
В частности, экспорт делает переменную доступной для дочерних процессов через среду.
Беано
15
Я также добавил бы, что если экспорт находится в файле, который вы «используете» (например, имя файла), то он также экспортирует его в вашу рабочую среду.
rogerdpack
6
@rogerdpack вы не можете сделать это без экспорта? кот> бла \ на = привет \ н. л; эхо $ а; выводит «привет» для меня.
Дэвид Винецкий
2
Приятно, что работает даже без экспорта. Поэтому я предполагаю, что при поиске файла, если вы используете экспорт, это отразится на дочерних процессах, а если вы этого не сделаете, это просто повлияет на локальную среду bash ...
rogerdpack
19
Есть один крайний случай к этому; name=value commandделает переменную доступной в подпроцессе command.
Оливер Чарльзуорт
254
Чтобы проиллюстрировать, что говорят другие ответы:
Еще один пример для этогоal$ foobar="Whatever" bash
Алун
70
Другие ответили, что экспорт делает переменную доступной для подоболочек, и это правильно, но это просто побочный эффект. Когда вы экспортируете переменную, она помещает эту переменную в среду текущей оболочки (то есть оболочка вызывает putenv(3)или setenv(3)).
Среда процесса наследуется через exec, делая переменную видимой в подоболочках.
Изменить (с перспективой на 5 лет): это глупый ответ. Цель «экспорта» состоит в том, чтобы сделать переменные «находящимися в среде последовательно выполняемых команд», независимо от того, являются ли эти команды подоболочками или подпроцессами. Наивной реализацией было бы просто поместить переменную в среду оболочки, но это сделало бы невозможной реализацию export -p.
Обратите внимание, что это не совсем так. В bash, export действительно добавляет переменную в среду текущей оболочки, но это не так dash. Мне кажется, что добавление переменной в среду текущей оболочки является самым простым способом реализации семантики export, но такое поведение не является обязательным.
Уильям Перселл
7
Я не уверен, что dashс этим связано. Оригинальный постер спрашивал конкретно о bash.
Морская звезда
14
Вопрос помечен, bashно в равной степени относится к любому варианту оболочки Борна. Быть слишком конкретным и давать ответы, относящиеся только к bashделу, - великое зло.
Уильям Перселл
12
bashэто jQuery оболочки.
Potherca
2
export makes the variable available to subshells, and that is correctЭто очень запутанное использование терминологии. Подоболочкам не нужно exportнаследовать переменные. Подпроцессы делают.
Амит Найду
62
Было сказано, что нет необходимости экспортировать в bash при порождении подоболочек, в то время как другие говорят прямо противоположное. Важно отметить разницу между подоболочками (те, которые созданы (), ``, $()или петля) и подпроцессы (процессы, которые вызываются по имени, например , буквальное bashпоявление в сценарии).
Суб оболочка будет иметь доступ ко всем переменным от родителя, независимо от их экспортируемого государства.
Суб процессы будут только увидеть экспортируемые переменные.
Общим в этих двух конструкциях является то, что ни один из них не может передавать переменные в родительскую оболочку.
Есть еще один источник путаницы: некоторые думают, что «разветвленные» подпроцессы - это те, которые не видят неэкспортированные переменные. Обычно за fork () сразу следуют exec (), и поэтому может показаться, что fork () - это то, что нужно искать, хотя на самом деле это exec (). Вы можете запускать команды без fork () сначала с помощью execкоманды, и процессы, запущенные этим методом, также не будут иметь доступа к неэкспортированным переменным:
Обратите внимание, что на parent:этот раз мы не видим строку, потому что мы заменили родительскую оболочку на execкоманду, поэтому для выполнения этой команды больше ничего не осталось.
Я никогда не видел цикл, который (сам по себе) создавал подоболочку; OTOH конвейер делает (всегда для частей, отличных от последнего, иногда для последнего в зависимости от вашей оболочки, версии и опций). Backgrounding ( &) также создает подоболочку.
dave_thompson_085
Как насчет этих 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.
4xy
31
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
Subprocess1 has B=BobSubprocess2 has B=Banana[1]+Done echo '(sleep 30; echo "Subprocess 1 has B=$B")'| bash
Только экспортированные переменные становятся частью среды ( man environ):
Следует отметить, что вы можете экспортировать переменную, а затем изменить значение. Измененное значение переменной будет доступно дочерним процессам. Как только экспорт был установлен для переменной, вы должны сделать, export -n <var>чтобы удалить свойство.
Спасибо, это именно та информация, которую я искал, потому что я увидел скрипт, который использовал переменные окружения, а затем «реэкспортировал» их с новым значением, и мне было интересно, нужно ли это.
Майк Липперт
8
Как вы, возможно, уже знаете, 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.
Обозначение переменных Bash (name = value) используется для установки локальных переменных, доступных только текущему процессу bash
Обозначение переменной Bash с префиксом другой команды создает переменную среды только для области действия этой команды.
bash vars не поддерживают столько типов, сколько Python, но имеют строковый, целочисленный и два вида массивов («индексированный» / традиционный и «ассоциативный», который похож на массив awk, perl-хэш или Python dict). Другие оболочки различаются; только строка переносима .
dave_thompson_085
7
Общепринятый ответ подразумевает это, но я хотел бы сделать явное соединение оболочки встроенных команд:
Как уже упоминалось, exportсделает переменную доступной как для оболочки, так и для дочерних элементов. Если exportэто не используется, то переменная будет доступна только в оболочке, и только оболочка встроенные команды могут получить к нему доступ.
Это,
tango=3
env | grep tango # prints nothing, since env is a child processset| grep tango # prints tango=3 - "type set" shows `set` is a shell builtin
Два из создателей UNIX, Брайан Керниган и Роб Пайк, объясняют это в своей книге «Среда программирования UNIX». Google для названия, и вы легко найдете PDF-версию.
Они обращаются к переменным оболочки в разделе 3.6 и фокусируются на использовании exportкоманды в конце этого раздела:
Если вы хотите, чтобы значение переменной было доступно в подоболочках, следует использовать команду экспорта оболочки. (Вы можете подумать, почему нет способа экспортировать значение переменной из вложенной оболочки в ее родительский объект).
По умолчанию переменные, созданные в скрипте, доступны только текущей оболочке; дочерние процессы (вложенные оболочки) не будут иметь доступа к значениям, которые были установлены или изменены. Чтобы дочерние процессы могли видеть значения, необходимо использовать команду экспорта.
Хотя это явно не упоминается в обсуждении, НЕ обязательно использовать экспорт при порождении подоболочки изнутри bash, поскольку все переменные копируются в дочерний процесс.
export name=value
это не портативно. В зависимости от того, что именно вы хотите, попробуйтеname=value; export name
портативное решение.Ответы:
export
делает переменную доступной для подпроцессов.Это,
означает, что имя переменной доступно любому процессу, который вы запускаете из этого процесса оболочки. Если вы хотите, чтобы процесс использовал эту переменную, используйте
export
и запустите процесс из этой оболочки.означает, что область действия переменной ограничена оболочкой и недоступна для любого другого процесса. Вы бы использовали это для (скажем) переменных цикла, временных переменных и т. Д.
Важно отметить, что экспорт переменной не делает ее доступной для родительских процессов. То есть, указание и экспорт переменной в порожденном процессе не делает ее доступной в процессе, который ее запустил.
источник
name=value command
делает переменную доступной в подпроцессеcommand
.Чтобы проиллюстрировать, что говорят другие ответы:
источник
al$ foobar="Whatever" bash
Другие ответили, что экспорт делает переменную доступной для подоболочек, и это правильно, но это просто побочный эффект. Когда вы экспортируете переменную, она помещает эту переменную в среду текущей оболочки (то есть оболочка вызывает
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
появление в сценарии).Общим в этих двух конструкциях является то, что ни один из них не может передавать переменные в родительскую оболочку.
Есть еще один источник путаницы: некоторые думают, что «разветвленные» подпроцессы - это те, которые не видят неэкспортированные переменные. Обычно за fork () сразу следуют exec (), и поэтому может показаться, что fork () - это то, что нужно искать, хотя на самом деле это exec (). Вы можете запускать команды без fork () сначала с помощью
exec
команды, и процессы, запущенные этим методом, также не будут иметь доступа к неэкспортированным переменным:Обратите внимание, что на
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
помечает имя переменной в среде, которая копирует подпроцессы и их подпроцессы при создании. Ни одно имя или значение никогда не копируются из подпроцесса.Распространенной ошибкой является размещение пробела вокруг знака равенства:
Подпроцесс
B
видит только экспортированную переменную ( ):Изменения в подпроцессе не изменяют основную оболочку:
Переменные, помеченные для экспорта, имеют значения, скопированные при создании подпроцесса:
Только экспортированные переменные становятся частью среды (
man environ
):Итак, теперь это должно быть так же ясно, как летнее солнце! Спасибо Брэйну Агнью, Александру и Уильяму Пруселлу.
источник
export
сделает переменную доступной для всех оболочек, разветвленных из текущей оболочки.источник
Следует отметить, что вы можете экспортировать переменную, а затем изменить значение. Измененное значение переменной будет доступно дочерним процессам. Как только экспорт был установлен для переменной, вы должны сделать,
export -n <var>
чтобы удалить свойство.источник
Как вы, возможно, уже знаете, 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
это не используется, то переменная будет доступна только в оболочке, и только оболочка встроенные команды могут получить к нему доступ.Это,
источник
Вот еще один пример:
Только с помощью export VARTEST значение VARTEST доступно в sudo bash -c '...'!
Для дальнейших примеров см .:
http://mywiki.wooledge.org/SubShell
bash-hackers.org/wiki/doku.php/scripting/processtree
источник
Просто чтобы показать разницу между экспортируемой переменной, находящейся в среде (env), и неэкспортированной переменной, не находящейся в среде:
Если я сделаю это:
тогда в env появляется только $ OURNAME. Переменная $ MYNAME отсутствует в env.
но переменная $ MYNAME существует в оболочке
источник
Два из создателей UNIX, Брайан Керниган и Роб Пайк, объясняют это в своей книге «Среда программирования UNIX». Google для названия, и вы легко найдете PDF-версию.
Они обращаются к переменным оболочки в разделе 3.6 и фокусируются на использовании
export
команды в конце этого раздела:источник
По умолчанию переменные, созданные в скрипте, доступны только текущей оболочке; дочерние процессы (вложенные оболочки) не будут иметь доступа к значениям, которые были установлены или изменены. Чтобы дочерние процессы могли видеть значения, необходимо использовать команду экспорта.
источник
Хотя это явно не упоминается в обсуждении, НЕ обязательно использовать экспорт при порождении подоболочки изнутри bash, поскольку все переменные копируются в дочерний процесс.
источник