Якщо процеси успадковують батьківське середовище, навіщо нам потрібен експорт?


72

Я читав тут, що мета exportоболонки - зробити змінну доступною для підпроцесів, запущених з оболонки.

Однак я також тут і тут читав, що "Процеси успадковують своє середовище від свого батька (процес, який їх запустив)".

Якщо це так, навіщо нам це потрібно export? Що я пропускаю?

Чи змінні оболонки за замовчуванням не є частиною середовища? Яка різниця?

Відповіді:


74

Ваше припущення полягає в тому, що змінні оболонки знаходяться в оточенні . Це неправильно. exportКоманда , що визначає ім'я , яке буде в навколишньому середовищі на всіх. Таким чином:

a=1 b=2
export b

призводить до того, що поточна оболонка знає, що вона $aрозширюється до 1 і $bдо 2, але підпроцеси нічого не знатимуть, aоскільки вона не є частиною середовища (навіть у поточній оболонці).

Деякі корисні інструменти:

  • set: Корисно для перегляду параметрів поточної оболонки, експортованих чи ні
  • set -k: Встановлює задані аргументи в оточенні. Розглянемоf() { set -k; env; }; f a=1
  • set -a: Показує оболонці, щоб розмістити будь-яке ім'я, яке встановлюється в оточення. Як поставити exportперед кожним завданням. Корисно для .envфайлів, як у set -a; . .env; set +a.
  • export: Показує оболонці, щоб ввести ім'я в оточення. Експорт та призначення - це дві абсолютно різні операції.
  • env: Як зовнішня команда, envможе розповісти вам лише про успадковане середовище, таким чином, це корисно для перевірки здоровості.
  • env -i: Корисно для очищення середовища перед запуском підпроцесу.

Альтернативи export:

  1. name=val command # Призначення перед тим, як команда експортує це ім'я до команди.
  2. declare/local -x name # Експорт імені, особливо корисного для функцій оболонки, коли ви хочете уникати піддавати ім'я сторонній області.
  3. set -a # Експорт кожного наступного завдання.

3
set -kце так, що можна використовувати cmd ENVVAR=valueзамість ENVVAR=value cmd, що не працюватиме у вашому прикладі, якщо не set -kбуло запущено до виклику f. Крім того, не багато снарядів підтримують його в наш час і лише для зворотної сумісності з оболонкою Борна. У оболонці Bourne (або Korn) це не працює для функцій. А оскільки це впливає на розбір оболонки, він повинен діяти в момент, коли оболонка читає код, який використовує там.
Стефан Хазелас

1
Ви також можете згадатиset -a
Стефан Шазелас

24

Існує різниця між змінними оболонки та змінними середовища. Якщо ви визначаєте змінну оболонки export, не враховуючи її, вона не додається до середовища процесів і, таким чином, не успадковується її дітям.

Використовуючи, exportви говорите оболонці, щоб додати змінну оболонки до середовища. Ви можете перевірити це, використовуючи printenv(що просто друкує його середовище stdout, оскільки це дочірній процес, ви бачите ефект від exportзмінних):

#!/bin/sh

MYVAR="my cool variable"

echo "Without export:"
printenv | grep MYVAR

echo "With export:"
export MYVAR
printenv | grep MYVAR

6

Після експорту змінна є частиною середовища. PATHекспортується в саму оболонку, тоді як спеціальні змінні можна експортувати за потреби. Використовуючи деякий код налаштування:

$ cat subshell.sh 
#!/usr/bin/env bash
declare | grep -e '^PATH=' -e '^foo='

Порівняйте

$ cat test.sh 
#!/usr/bin/env bash
export PATH=/bin
export foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test.sh 
PATH=/bin
foo=bar
PATH=/bin
foo=bar

З

$ cat test2.sh 
#!/usr/bin/env bash
PATH=/bin
foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test2.sh 
PATH=/bin
foo=bar
PATH=/bin

Оскільки fooоболонка test2.shне експортується і ніколи не експортується, вона не була частиною середовища subshell.shв останньому циклі.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.