Відповіді:
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 identifierBПідпроцес бачить лише експортовану змінну ( ):
$ 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знайти портативне рішення.