Що саме є змінною середовища?


42

Я знаю, що VARIABLE=valueстворює змінну середовища і export VARIABLE=valueробить її доступною для процесів, створених поточною оболонкою. envпоказує поточні змінні середовища, але де вони живуть? Що включає змінна середовище (або середовище для цього питання)?

Відповіді:


29

Навколишнє середовище не таке магічне, як може здатися. Оболонка зберігає її в пам'яті і переходить до execve()системного виклику. Дочірній процес успадковує його як вказівник масиву, який називається environ. На сторінці сторінки execve:

СИНОПИС

   #include <unistd.h>

   int execve(const char *filename, char *const argv[],
              char *const envp[]);

argv- це масив аргументів, переданих новій програмі.
За умовою, перший із цих рядків повинен містити ім'я файлу, пов'язане з файлом, який виконується. envpце масив рядків, умовно форми form key = значення, які передаються як середовище новій програмі.

Сторінка environ(7)також пропонує деяку інформацію:

СИНОПИС

   extern char **environ;

ОПИС

Змінна environвказує на масив покажчиків на рядки під назвою "середовище". Останній покажчик у цьому масиві має значення NULL. (Ця змінна повинна бути оголошена в користувацькій програмі, але оголошена у файлі заголовка <unistd.h>у випадку, якщо файли заголовків походять від libc4 або libc5, а якщо вони надходять від glibc та визначено _GNU_SOURCE.) Цей масив рядків надається для процес за допомогою виклику exec (3), який запустив процес.

Обидва ці програми GNU відповідають специфікації POSIX


4
+1, мабуть, варто зазначити, що деякі члени exec(3)родини (тобто ті, що не відповідають exec * v) проходять ** оточення під кришками.
msw

5
Зауважте, що йдеться не про дочірні процеси (дочірні процеси успадковують усю пам’ять свого батька), а виконані програми (в тому ж процесі), тож це ще один спосіб передачі даних через системний виклик execve () (який інакше стирає пам'ять процесу).
Стефан Шазелас

@msw: Це exec*eваріанти явно передають env, а не неявно використовують environглобальну змінну. Засіб v"вектор" і посилається на аргументи командного рядка, передані як масив (а не "список" (функція змінної довжини)) execve- це системний виклик, а всі інші exec*функції - це обгортки libc.
Пітер Кордес

19

Ви зрозуміли це лише трохи неправильно: SOME_NAME=valueстворює змінну оболонки (у більшості оболонок). export SOME_NAME=valueстворює змінну середовища. Для кращого для гіршого, більшість оболонок BSD Unix / Linux / * використовують ідентичний синтаксис для доступу до змінних середовища та змінних оболонок.

У певному сенсі «середовище» - це лише інформація, яка йде разом із виконанням програми. У програмах на мові Сі, ви можете знайти ідентифікатор процесу з getpid()викликом, в програмній оболонці ви будете використовувати доступ до змінному: $$. Ідентифікатор процесу - лише частина середовища програми. Я вважаю, що термін "середовище" походить від деяких більш теоретичних тем з інформатики, як моделювання виконання програми. Моделі виконання програми мають середовище, "яке містить асоціації між змінними та їх значеннями".

І останнє, більш чітке визначення - це те, що "середовище" для оболонок Unix / Linux / * BSD: асоціація між іменами ("змінними") та їх значеннями. Для більшості оболонок у стилі Unix значення - це всі символьні рядки, хоча це не так суворо, як це було раніше. Усі Ksh, Zsh та Bash сьогодні ввели змінні. Навіть визначення функції оболонки можна експортувати.

Використання середовища, відокремленого від звичайних змінних оболонок, передбачає fork/execметод запуску нового процесу, який використовують усі Unixes. Коли ви exportімені / значення пари, пара імен / значення буде присутній в середовищі нових виконуваних файлів, запущених оболонкою із execve(2)системним викликом (зазвичай після a fork(2), за винятком випадків, коли execбула використана команда shell).

Слідом execve()за main()функцією нового бінарного файлу є його аргументи командного рядка, середовище (зберігається у вигляді масиву покажчиків на var=valueрядки, що закінчується NULL , див. environ(7)Сторінку man). Інший стан, який успадковується, включає ulimitналаштування, поточний робочий каталог та будь-які дескриптори відкритих файлів, для яких execve()абонент не встановив FD_CLOEXEC. Поточний стан tty (увімкнено ехо, необроблений режим тощо) також може вважатися частиною стану виконання, успадкованого нововиявленим execпроцесом.

Дивіться bashопис посібника в середовищі виконання простих команд (крім функцій вбудованої або оболонки).

Середовище Unix відрізняється принаймні від деяких інших операційних систем: «Лексика» VMS може бути змінена дочірнім процесом, і ця зміна була помітна у батьків. VMS cdв дочірньому процесі вплине на робочий каталог батьків. Принаймні, в деяких обставинах, і моя пам’ять, можливо, не вдається.

Деякі змінні середовища добре відомі, $HOME, $PATH, $LD_LIBRARY_PATHта інші. Деякі з них є звичайними для даної програми програмування, так що батьківська оболонка може передавати багато і багато інформації спеціального призначення в якусь програму, наприклад, конкретний тимчасовий каталог або ідентифікатор користувача та пароль, які не відображаються в ps -ef. Прості програми CGI, наприклад, передають багато інформації з веб-сервера через змінні середовища.


1
Здавалося б, все-таки трохи складніше. Принаймні в bash SOME_NAME=value commandбуде встановлено змінну середовища SOME_NAME для виклику цієї команди. Незрозуміло, схоже, це не встановлює однойменну змінну оболонки.
Samuel Edwin Ward

2
Якщо точніше, змінні середовища не успадковуються, а явно передаються з оболонки програмам, які вона породжує.
msw

2
@SamuelEdwinWard Причина того, що ви поводите SOME_NAME=value commandсебе всупереч вашим очікуванням, полягає в тому, що це спеціальний синтаксис, що означає "додати SOME_NAME до середовища, переданого команді, але інакше не змінюйте змінні цієї оболонки".
msw

1
Захоплююче, посилання на обчислення лямбда / функціональне програмування. Це цікавий зв’язок, який має багато сенсу.
Метт

1
Дещо з цього не зовсім правильно. Наприклад, подоболочкі є підпроцесами і має бути fork()ед, але вони роблять отримати (копію) змінну оболонки.
ruakh

7

Змінні середовища в їх найновішому вигляді є лише набором пар імен / значень. Як описано на сторінці bash man ( man 1 bash) у розділі ЕКОЛОГІЯ:

   When  a  program  is invoked it is given an array of strings called the
   environment.   This  is  a  list  of  name-value  pairs,  of  the  form
   name=value.

   The  shell  provides  several  ways  to manipulate the environment.  On
   invocation, the shell scans its own environment and creates a parameter
   for  each name found, automatically marking it for export to child pro-
   cesses.  Executed commands inherit the  environment.

На практиці він дозволяє визначити поведінку, яка є спільною або унікальною для програм, викликаних з цієї оболонки. Наприклад, при використанні crontabабо visudoви можете визначити EDITORзмінну середовища для визначення іншого редактора, відмінного від того, який використовувала б ваша система за замовчуванням. Це може бути справедливим і для таких речей, як manкоманда, яка розглядає ваше PAGERсередовище, щоб розробити, яку програму пейджера слід використовувати для відображення результатів сторінки man.

Дуже багато команд unix читають середовище і залежно від того, що там встановлено, змінюють їх вихід / обробку / дії залежно від них. Деякі є спільними, деякі - унікальними для програми. Більшість основних сторінок містять інформацію про те, як змінна середовища впливає на описану програму.

Інші практичні ілюстрації стосуються таких речей, як системи з кількома встановленнями Oracle на одній платформі. Встановивши ORACLE_HOME, весь набір команд oracle (як завантажений із PATHзмінної середовища) потім витягніть налаштування, визначення, відображення та бібліотеки з-під цього каталогу верхнього рівня. Те ж саме стосується інших програм, таких як java із JAVA_HOMEзмінною середовища.

Баш сам по собі має багато змінну середовища , які можуть змінити поведінку цілого ряду речей з історії ( HISTSIZE, і HISTFILEт.д.), розміру екрана ( COLUMNS), завершення вкладки ( FIGNORE, GLOBIGNORE) Мови і кодування символів / декодування ( LANG, LC_*), швидкі ( PS1.. PS4), і тощо (знову шукайте знання зі сторінки bash man).

Також ви можете писати сценарії / програми, які використовують ваші власні змінні індивідуального середовища (для передачі налаштувань або зміни функціональності).


0

"Змінні середовища" - це набір динамічних названих значень, які можуть впливати на поведінку запущених процесів на комп'ютері.

Вони є частиною операційного середовища, в якому працює процес. Наприклад, запущений процес може запитувати значення змінної середовища TEMP, щоб виявити підходяще місце для зберігання тимчасових файлів, або змінну HOME або USERPROFILE для пошуку структури каталогів, що належить користувачеві, який керує процесом.

Більше інформації тут → http://en.wikipedia.org/wiki/Environment_variable .

Все, що ви хочете знати про змінні середовища ... ↑


1
Хоча навряд чи це посилання відійде, краще відповісти на питання тут відповідним текстом та надати посилання як доповнення до резервної інформації.
Антон

@Anthon Я вважаю, що ви правильні, і я внесу зміни, як тільки зможу ... Дякую за пораду ...
SoCalDiegoRob

-1

Ця відповідь вимагає певного досвіду та знань сценаріїв оболонок із термінами змінна, значення, підміна змінної, підказка, ехо, ядро, оболонка, утиліта, сеанс та процес.

Мінлива оточення (envar) являє собою набір глобальних певних змінних , які можуть вплинути на те , як ці процеси будуть вести себе в операційній системі комп'ютера.

1. Зразковий вступ:

Ми замінюємо envars великими $та великими літерами . Наприклад: $PS1.

Ми можемо надрукувати envar таким чином:

echo $PS1

$PS1містить значення підказки Unix. Скажіть, його рідні значення є \u \w $.

  • \u означає (поточний) користувач,
  • \w стенди для робочого каталогу,
  • $ - це межувати підказку.

Отже, якщо ми це робимо: echo $PS1ми бачимо значення \u, \wплюс знак долара в кінці кінців.

Ми могли б змінити поведінку Unix у цьому контексті, якщо змінимо значення цього envar. Наприклад:

PS1="\w >"

Тепер підказка виглядає приблизно так (припустимо, що робоча директорія названа "John"):

John >

Таким же чином, як ми могли зробити PS1="Hello, I'm your prompt >"це echo $PS1, ми принесемо:

Hello, I'm your prompt >

У Bash 4.xx ми можемо друкувати ВСІ envavs у системі за допомогою envкоманди. Я пропоную виконати envв терміналі і поглянути на вихід.

2. Як ці дані відображаються та обробляються:

Термінал сеансу дозволить нам налаштувати envars, які йдуть з Bash.

Вищезазначені зміни зазвичай є тимчасовими, і ось чому:

Кожен сеанс (який не є підсеансом) є унікальним, і декілька процесів можуть запускатися одночасно (кожен зі своїм набором envars), але зазвичай є спадкування від сеансу 0 до сеансу 1 і вище.

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

Тож як ми можемо зберегти ці зміни:

Існує кілька типів способів зберігання змін envar, залежно від обсягу, який ми вибираємо. Ось різні сфери (рівні) для таких змін:

  • Рівень процесу: envars доступний лише для програм у поточному сеансі.
  • Рівень експорту: Envars доступний для програм на поточному сеансі або всіх його підсесій .
  • Глобальний рівень: зміни зберігатимуться для всіх сеансів (первинного та всіх допоміжних).

Де зберігаються дані envar:

Unix побудований з 3 основних шарів: ядра, оболонки та утиліти. Кожна оболонка AFAIK має власну оболонку, і вони побудовані головним чином або виключно в оболонці.

Конкретне місце, в якому глобально змінити їх, зазвичай, /etc/profileхоча ми можемо це зробити, .bashrcзвичайно.

3. Створення нових прихильників:

Ми можемо створити нові прихильники, і ось спосіб; станом на Bash 4.xx немає назви рідного енавера MESSAGE(як сказано, envars, як правило, з великої літери).

MESSAGE="Hello world!"

створить це для нас, і тепер, якщо ми наберемо ехо $MESSAGE, ми отримуємо hello world!.

Якщо ми виконаємо bashв нашому поточному робочому сеансі (вікні), ми запустимо нову підсесію bash і більше не буде працювати в початковому процесі, якщо ми не виконаємо exit.

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

Примітка: Не використовуйте спеціальні знаки для значень envar, таких як! або вони не будуть врятовані

Експорт envar з початкового сеансу на всі підсесії:

Ми все ще можемо використовувати envar, створений у першому сеансі, у другому, також не реєструючи його у конфіденційних файлах користувача чи глобального рівня (див. Наступні дані). Ось як це зробити:

Перейдіть на початковий сеанс (будь то в поточному вікні чи іншому) та виконайте:

export MESSAGE

під час експорту не використовуйте $знак.

Зараз він експортується на всі підсесії. Якщо ви будете робити echo $MESSAGEна підсеансі, будь то від вашого користувача чи іншого, він буде надрукований.

Зауважте, що внутрішні змінні Shell, такі як PS1не слід експортувати, але якщо ви хочете експортувати їх з будь-якої причини, і вони не з'являються, не виконуйте bashпісля export, а скоріше bash –norc.

4. Енвар $ PATH:

$PATH це envar, який користувачі зазвичай найбільше змінюють.

Якщо ми echo $PATH, ми будемо бачити цей потік:

/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

Друковані значення цього envar розділені двокрапками (:) там, але ось потенційно більш комфортний спосіб (це ті самі значення):

/usr/local/bin
/usr/bin
/bin
/usr/local/games
/usr/games

Це директиви для пошуку, коли ми запускаємо утиліту.

Виконавши, which echoми отримаємо його розташування файлу - наприклад, ми можемо побачити, що він існує в /bin/echo.

Виходячи з цього, нам не потрібно вводити echo envar для перегляду значень evnar. Ми також можемо:

/bin/echo $ENVAR

Envar все ще буде виконаний, наприклад:

/bin/echo $HOME

Дає нам

/home/User || /root

Так як:

echo $HOME

Дає нам

/home/User || /root

Примітка: $HOMEскорочено як ~.

Відносини системи - $ PATH та можлива взаємодія з користувачем:

У Bash 4.xx, коли ми використовуємо утиліту без її повного шляху, система буде використовувати всі 6 згаданих вище значень $PATHenvar. Отже, воно почнеться з того /user/local/bin, і слідкує за усім його вмістом, шукаючи echoвиконуваний файл.

У цьому випадку він зупиниться на тому /bin/echo, в якому в цьому випадку виконується виконуваний файл.

Отже, головна причина, з якої ми можемо налаштувати $PATHenvar, - це встановлення виконуваних файлів, які не належать до жодних його початкових значень.

Встановивши такі виконувані файли, ми повинні встановити їх $PATHзначення відповідно, і тоді ми зможемо з ними працювати.

5. Додаток - розширення $PATH:

Ми можемо export $PATHвиконати базові підсеанси (що включає розширення bash типу WP-CLI для WordPress або Drush for Drupal) таким чином:

export PATH="/home/John:$PATH"

Це додасть нове значення /home/Johnдо $PATH, а потім відразу після цього, він буде анексувати будь-які власні значення до нього (відразу після двокрапки), які зберігаються під синтаксисом $PATH.

Такі постійні зміни можуть бути зроблені у відповідному сценарії, як правило, під /etc/profileіменем та під ім'ям .bashrc.


3
У цій відповіді є дуже багато неправильного: зв'язок сеансів та процесів, попередження про те, !що значення змінної середовища не працює, що знаходиться прямо під прикладом, що показує його роботу, помилкове поняття про підсеанси, досить химерні поради щодо того, що робити після експорту змінної оболонки та помилкового уявлення про глобальні змінні середовища.
JdeBP

warning about ! in an environment variable value not working that is right below an example showing it working? Будь ласка, приклад.
JohnDoea

quite bizarre advice about what to do after exporting a shell variable, що саме ти маєш на увазі?
JohnDoea

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