Відповіді:
Навколишнє середовище не таке магічне, як може здатися. Оболонка зберігає її в пам'яті і переходить до 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 згаданих вище значень $PATH
envar. Отже, воно почнеться з того /user/local/bin
, і слідкує за усім його вмістом, шукаючи echo
виконуваний файл.
У цьому випадку він зупиниться на тому /bin/echo
, в якому в цьому випадку виконується виконуваний файл.
Отже, головна причина, з якої ми можемо налаштувати $PATH
envar, - це встановлення виконуваних файлів, які не належать до жодних його початкових значень.
Встановивши такі виконувані файли, ми повинні встановити їх $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) проходять ** оточення під кришками.