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

что это export для чего?

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

export name=value

и

name=value

14 ответов


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

то есть

export name=value

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

name=value

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

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


чтобы проиллюстрировать, что говорят другие ответы:

$ foo="Hello, World"
$ echo $foo
Hello, World
$ bar="Goodbye"
$ export foo
$ bash
bash-3.2$ echo $foo
Hello, World
bash-3.2$ echo $bar

bash-3.2$ 

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

Edit (с 5-летней перспективой): это глупый ответ. Цель "экспорта" - сделать переменные " быть в среда последовательно выполняемых команд", будь то подрешетки или подпроцессы. Наивной реализацией было бы просто поместить переменную в среду оболочки, но это сделало бы невозможным реализовать export -p.


было сказано, что нет необходимости экспортировать в 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()s сразу следуют exec() s, и поэтому кажется, что fork () - это то, что нужно искать, в то время как на самом деле это exec (). Ты можешь бежать. команды без fork()ING сначала с exec команда, и процессы, запущенные этим методом, также не будут иметь доступа к несообщаемым переменным:

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

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


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 сделает переменную доступной для всех оболочек, раздвоенных из текущей оболочки.


следует отметить, что вы можете экспортировать переменную, а затем изменить ее значение. Измененное значение переменной будет доступно дочерним процессам. После того, как экспорт был установлен для переменной, вы должны сделать 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);

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

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

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

больше на окружающая среда в Баш

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

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

подробнее о Параметры Оболочки (включая переменные)

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

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


в итоге:

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

на принято отвечать подразумевает это, но я хотел бы сделать явное соединение с Shell builtins:

как уже упоминалось, export сделает переменную доступной как для оболочки, так и для детей. Если export is не используется переменная будет доступна только в оболочке, а оболочка только builtins может получить к нему доступ.

то есть

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 '...'!

для дальнейших примеров см.:


чтобы показать разницу между экспортируемой переменной, находящейся в среде (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.