Відповіді:
export
робить змінну доступною для підпроцесів.
Це є,
export name=value
означає, що ім'я змінної доступне для будь-якого процесу, який ви запускаєте з цього процесу оболонки. Якщо ви хочете, щоб процес використовував цю змінну, використовуйте export
та запустіть процес із цієї оболонки.
name=value
означає, що змінна область обмежена оболонкою і не доступна для будь-якого іншого процесу. Ви б використовували це для (скажімо) змінних циклу, тимчасових змінних тощо.
Важливо зазначити, що експорт змінної не робить її доступною для батьківських процесів. Тобто, вказівка та експорт змінної у спареному процесі не робить її доступною у процесі, який її запустив.
name=value command
робить змінну доступною в підпроцесі command
.
Інші відповіли, що експорт робить змінну доступною для підрозділів, і це правильно, але лише побічний ефект. Коли ви експортуєте змінну, вона розміщує цю змінну в середовищі поточної оболонки (тобто оболонки викликає putenv(3)
або setenv(3)
).
Середовище процесу успадковується через exec, що робить змінну видимою в підшах.
Правка (з перспективою 5 років): це дурна відповідь. Мета "експорту" полягає в тому, щоб змінні "опинилися в оточенні команд, що виконуються згодом", будь то ці команди підзагортами або підпроцесами. Наївною реалізацією було б просто помістити змінну в середовище оболонки, але це зробило б неможливим реалізацію export -p
.
bash
експорті дійсно додати змінний в середу поточної оболонки, але це не той випадок з dash
. Мені здається, що додавання змінної до середовища поточної оболонки є найпростішим способом реалізації семантики export
, але така поведінка не є обов'язковою.
dash
стосується цього. Оригінальний плакат питав конкретно о bash
.
bash
але однаково стосується будь-якого варіанта бурно-оболонки. Бути надмірно конкретним та надавати відповіді, які стосуються лише bash
- це велике зло.
bash
- jQuery оболонки.
export makes the variable available to subshells, and that is correct
Це дуже заплутане використання термінології. Абонентам не потрібно export
успадковувати змінні. Підпроцеси роблять.
Було сказано, що не потрібно експортувати в баш при нерестування передпластів, в той час як інші кажуть, що навпаки. Важливо відзначити різницю між подоболочкі (ті, які створені ()
, ``
, $()
або петля) і підпроцеси (процеси, які викликаються по імені, наприклад , буквальне 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 (), спочатку за допомогою 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
(без ;
) стосується породженого підпроцесу якось, оскільки оболонка походження не має нічого спільного з цим. 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 і не мають нічого спільного зі змінними середовища, що зберігаються в операційній системі.
Детальніше про параметри оболонки (включаючи змінні)
Також варто зазначити, що відповідно до посібника Баша:
Навколишнє середовище для будь-якої простої команди чи функції може бути тимчасово доповнене, додавши її до присвоєння параметрів, як описано в параметрах оболонки . Ці заяви про присвоєння впливають лише на середовище, яке бачить ця команда.
Підводячи підсумки:
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}"'
Тільки за допомогою експорту VARTEST значення VARTEST доступне у sudo bash -c '...'!
Для подальших прикладів див:
bash-hackers.org/wiki/doku.php/scripting/processtree
Два із творців UNIX, Брайан Керніган та Роб Пайк, пояснюють це у своїй книзі "Середовище програмування UNIX". Google за назвою, і ви легко знайдете версію PDF.
Вони звертаються до змінних оболонок у розділі 3.6 та зосереджуються на використанні export
команди в кінці цього розділу:
Коли ви хочете зробити значення змінної доступною в під оболонках, слід використовувати команду експорту оболонки. (Ви можете подумати про те, чому немає способу експортувати значення змінної з підколі в її батьківський).
Просто щоб показати різницю між експортованою змінною, що знаходиться в середовищі (env), і неекспортованою змінною, яка не знаходиться в середовищі:
Якщо я це роблю:
$ MYNAME=Fred
$ export OURNAME=Jim
тоді у env з'являється лише $ OURNAME. Змінна $ MYNAME відсутня в env.
$ env | grep NAME
OURNAME=Jim
але змінна $ MYNAME існує в оболонці
$ echo $MYNAME
Fred
Хоча явно не зазначено в обговоренні, НЕ потрібно використовувати експорт під час нерестування підзаголовка з внутрішньої частини bash, оскільки всі змінні копіюються в дочірній процес.
export name=value
це не портативно. Залежно від того, що саме ви хочете, спробуйтеname=value; export name
знайти портативне рішення.