Відповіді:
Навколишнє середовище не таке магічне, як може здатися. Оболонка зберігає її в пам'яті і переходить до 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
exec*eваріанти явно передають env, а не неявно використовують environглобальну змінну. Засіб v"вектор" і посилається на аргументи командного рядка, передані як масив (а не "список" (функція змінної довжини)) execve- це системний виклик, а всі інші exec*функції - це обгортки libc.
Ви зрозуміли це лише трохи неправильно: 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, наприклад, передають багато інформації з веб-сервера через змінні середовища.
SOME_NAME=value commandбуде встановлено змінну середовища SOME_NAME для виклику цієї команди. Незрозуміло, схоже, це не встановлює однойменну змінну оболонки.
SOME_NAME=value commandсебе всупереч вашим очікуванням, полягає в тому, що це спеціальний синтаксис, що означає "додати SOME_NAME до середовища, переданого команді, але інакше не змінюйте змінні цієї оболонки".
fork()ед, але вони роблять отримати (копію) змінну оболонки.
Змінні середовища в їх найновішому вигляді є лише набором пар імен / значень. Як описано на сторінці 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).
Також ви можете писати сценарії / програми, які використовують ваші власні змінні індивідуального середовища (для передачі налаштувань або зміни функціональності).
"Змінні середовища" - це набір динамічних названих значень, які можуть впливати на поведінку запущених процесів на комп'ютері.
Вони є частиною операційного середовища, в якому працює процес. Наприклад, запущений процес може запитувати значення змінної середовища TEMP, щоб виявити підходяще місце для зберігання тимчасових файлів, або змінну HOME або USERPROFILE для пошуку структури каталогів, що належить користувачеві, який керує процесом.
Більше інформації тут → http://en.wikipedia.org/wiki/Environment_variable .
Все, що ви хочете знати про змінні середовища ... ↑
Ця відповідь вимагає певного досвіду та знань сценаріїв оболонок із термінами змінна, значення, підміна змінної, підказка, ехо, ядро, оболонка, утиліта, сеанс та процес.
Мінлива оточення (envar) являє собою набір глобальних певних змінних , які можуть вплинути на те , як ці процеси будуть вести себе в операційній системі комп'ютера.
Ми замінюємо 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в терміналі і поглянути на вихід.
Термінал сеансу дозволить нам налаштувати envars, які йдуть з Bash.
Вищезазначені зміни зазвичай є тимчасовими, і ось чому:
Кожен сеанс (який не є підсеансом) є унікальним, і декілька процесів можуть запускатися одночасно (кожен зі своїм набором envars), але зазвичай є спадкування від сеансу 0 до сеансу 1 і вище.
Зміни, які ми вносимо в один процес, є унікальними для нього, і вони припиняться, якщо закриємо його, не зберігаючи їх якимось чином.
Існує кілька типів способів зберігання змін envar, залежно від обсягу, який ми вибираємо. Ось різні сфери (рівні) для таких змін:
Unix побудований з 3 основних шарів: ядра, оболонки та утиліти. Кожна оболонка AFAIK має власну оболонку, і вони побудовані головним чином або виключно в оболонці.
Конкретне місце, в якому глобально змінити їх, зазвичай, /etc/profileхоча ми можемо це зробити, .bashrcзвичайно.
Ми можемо створити нові прихильники, і ось спосіб; станом на Bash 4.xx немає назви рідного енавера MESSAGE(як сказано, envars, як правило, з великої літери).
MESSAGE="Hello world!"
створить це для нас, і тепер, якщо ми наберемо ехо $MESSAGE, ми отримуємо hello world!.
Якщо ми виконаємо bashв нашому поточному робочому сеансі (вікні), ми запустимо нову підсесію bash і більше не буде працювати в початковому процесі, якщо ми не виконаємо exit.
Примітка. В операційних системах з термінальним емулятором (наприклад, на робочому столі Ubuntu) підсеанс зазвичай працює в тому ж вікні, але новий сеанс в іншому вікні не є підсеансом існуючого (це суміжний процес) .
Примітка: Не використовуйте спеціальні знаки для значень envar, таких як! або вони не будуть врятовані
Ми все ще можемо використовувати envar, створений у першому сеансі, у другому, також не реєструючи його у конфіденційних файлах користувача чи глобального рівня (див. Наступні дані). Ось як це зробити:
Перейдіть на початковий сеанс (будь то в поточному вікні чи іншому) та виконайте:
export MESSAGE
під час експорту не використовуйте $знак.
Зараз він експортується на всі підсесії. Якщо ви будете робити echo $MESSAGEна підсеансі, будь то від вашого користувача чи іншого, він буде надрукований.
Зауважте, що внутрішні змінні Shell, такі як PS1не слід експортувати, але якщо ви хочете експортувати їх з будь-якої причини, і вони не з'являються, не виконуйте bashпісля export, а скоріше bash –norc.
$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скорочено як ~.
У Bash 4.xx, коли ми використовуємо утиліту без її повного шляху, система буде використовувати всі 6 згаданих вище значень $PATHenvar. Отже, воно почнеться з того /user/local/bin, і слідкує за усім його вмістом, шукаючи echoвиконуваний файл.
У цьому випадку він зупиниться на тому /bin/echo, в якому в цьому випадку виконується виконуваний файл.
Отже, головна причина, з якої ми можемо налаштувати $PATHenvar, - це встановлення виконуваних файлів, які не належать до жодних його початкових значень.
Встановивши такі виконувані файли, ми повинні встановити їх $PATHзначення відповідно, і тоді ми зможемо з ними працювати.
$PATH:Ми можемо export $PATHвиконати базові підсеанси (що включає розширення bash типу WP-CLI для WordPress або Drush for Drupal) таким чином:
export PATH="/home/John:$PATH"
Це додасть нове значення /home/Johnдо $PATH, а потім відразу після цього, він буде анексувати будь-які власні значення до нього (відразу після двокрапки), які зберігаються під синтаксисом $PATH.
Такі постійні зміни можуть бути зроблені у відповідному сценарії, як правило, під /etc/profileіменем та під ім'ям .bashrc.
!що значення змінної середовища не працює, що знаходиться прямо під прикладом, що показує його роботу, помилкове поняття про підсеанси, досить химерні поради щодо того, що робити після експорту змінної оболонки та помилкового уявлення про глобальні змінні середовища.
warning about ! in an environment variable value not working that is right below an example showing it working? Будь ласка, приклад.
quite bizarre advice about what to do after exporting a shell variable, що саме ти маєш на увазі?
false notion of global environment variables, що саме ти маєш на увазі?
exec(3)родини (тобто ті, що не відповідають exec * v) проходять ** оточення під кришками.