Ответы:
Окружающая среда не так волшебна, как может показаться. Оболочка сохраняет его в памяти и переходит к execve()
системному вызову. Дочерний процесс наследует его как вызываемый указатель массива environ
. Из execve
справочной страницы:
СИНТАКСИС
#include <unistd.h> int execve(const char *filename, char *const argv[], char *const envp[]);
argv
массив строк аргументов, переданных новой программе
По соглашению первая из этих строк должна содержать имя файла, связанное с исполняемым файлом.envp
представляет собой массив строк, обычно в форме ключ = значение, которые передаются в качестве среды для новой программы.
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()
вызовом, в программной оболочке вы будете использовать доступ к переменному: $$
. Идентификатор процесса является лишь частью среды программы. Я считаю, что термин «среда» происходит от некоторых более теоретических тем компьютерных наук, таких как моделирование выполнения программ. Модели выполнения программ имеют среду, «которая содержит ассоциации между переменными и их значениями».
И последнее, более строгое определение - это «среда» для оболочек BSD Unix / Linux / *: связь между именами («переменными») и их значениями. Для большинства оболочек в стиле Unix значения являются символьными строками, хотя это не так строго, как раньше. В наши дни Ksh, Zsh и Bash имеют типизированные переменные. Даже определения функций оболочки могут быть экспортированы.
Использование среды, отдельной от простых переменных оболочки, включает fork/exec
метод запуска нового процесса, который используют все Unixes. Когда вы export
используете пару имя / значение, эта пара имя / значение будет присутствовать в среде новых исполняемых файлов, запускаемых оболочкой с помощью execve(2)
системного вызова (обычно после a fork(2)
, за исключением случаев, когда использовалась exec
команда оболочки).
После execve()
, main()
функция new двоичного файла имеет свои аргументы командной строки, среду (хранится в виде массива указателей на var=value
строки, заканчивающегося NULL , см. environ(7)
Справочную страницу). Другое наследуемое состояние включает в себя 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()
эд, но они делают получить (копию) переменную оболочки.
Переменные окружения в их исходной форме - это просто набор пар имя / значение. Как описано в man-странице bash ( man 1 bash
) в разделе ENVIRONMENT:
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
среду, чтобы определить, какую программу пейджера следует использовать для отображения выходных данных справочной страницы.
Довольно много команд unix читают окружение и в зависимости от того, что там установлено, изменяют их вывод / обработку / действие в зависимости от них. Некоторые из них являются общими, некоторые являются уникальными для программы. Большинство man-страниц содержат информацию о том, как переменная окружения влияет на описанную программу.
Другие практические иллюстрации приведены для таких вещей, как системы с несколькими установками Oracle на одной платформе. Установив ORACLE_HOME
весь набор команд оракула (загружаемых из PATH
переменной среды), вы извлекаете настройки, определения, сопоставления и библиотеки из этого каталога верхнего уровня. То же самое относится и к другим программам, таким как Java, с его JAVA_HOME
переменной окружения.
Сам bash имеет много переменных окружения, которые могут изменить поведение ряда вещей, таких как история ( HISTSIZE
и HISTFILE
т. д.), размер экрана ( COLUMNS
), локализация табуляции ( FIGNORE
, GLOBIGNORE
), локализация и кодировка / декодирование символов ( LANG
, LC_*
), подсказка ( PS1
.. PS4
) и и так далее (снова ищите знания на странице руководства bash).
Также вы можете писать скрипты / программы, которые используют ваши собственные переменные среды (для передачи настроек или изменения функциональности).
«Переменные среды» - это набор динамических именованных значений, которые могут влиять на поведение запущенных процессов на компьютере.
Они являются частью операционной среды, в которой выполняется процесс. Например, запущенный процесс может запросить значение переменной среды 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 >
Точно так же, как мы могли бы сделать PS1="Hello, I'm your prompt >"
, поэтому echo $PS1
принесет:
Hello, I'm your prompt >
В Bash 4.xx мы можем напечатать ВСЕ envars в системе с помощью env
команды. Я предлагаю выполнить env
в терминале и взглянуть на вывод.
Терминал сеанса позволяет нам настроить envars, которые идут с Bash.
Вышеуказанные изменения обычно носят временный характер, и вот почему:
Каждый сеанс (который не является вложенным сеансом) является уникальным, и несколько процессов могут выполняться уникально одновременно (каждый со своим собственным набором envars), но обычно существует наследование от сеанса 0 к сеансу 1 и выше.
Изменения, которые мы вносим в один процесс, уникальны для него и прекратятся, если мы закроем его, не сохранив их каким-либо образом.
Существует несколько типов способов хранения изменений envar в зависимости от выбранной области. Вот разные области (уровни) для таких изменений:
Unix состоит из 3 основных уровней: ядра, оболочки и утилит. AFAIK каждая оболочка имеет свои собственные envars, и они построены в основном или исключительно в оболочке.
Конкретное место, где можно глобально изменить их, обычно, /etc/profile
хотя мы также можем сделать это, .bashrc
конечно.
Мы можем создать новые envars, и вот способ; Начиная с Bash 4.xx, нет никакого собственного имени enavar MESSAGE
(как уже говорилось, envars обычно в верхнем регистре).
MESSAGE="Hello world!"
создаст его для нас, и теперь, если мы введем echo $MESSAGE
, мы получим hello world!
.
Если мы будем выполнять bash
в нашем текущем рабочем сеансе (окне), мы запустим новую подсессию bash и больше не будем работать в исходном процессе, если мы не выполним exit
.
Примечание. В операционных системах с эмулятором терминала (например, рабочим столом Ubuntu) субсессия обычно выполняется в том же окне, но новый сеанс в другом окне не является субсессией существующего (это смежный процесс). ,
Примечание: не используйте специальные знаки в значениях envar, такие как! или они не будут спасены.
Мы по-прежнему можем использовать envar, созданный в первом сеансе, а также во втором сеансе, без регистрации его в пользовательских файлах или файлах глобального уровня (см. Следующие данные). Вот как это сделать:
Перейти к исходному сеансу (в текущем или другом окне) и выполнить:
export MESSAGE
при экспорте не используйте $
знак.
Теперь он экспортируется во все подсессии. Если вы будете выполнять echo $MESSAGE
в подсессии, от вашего пользователя или другого, он будет напечатан.
Обратите внимание, что внутренние переменные оболочки, такие как, PS1
не должны экспортироваться, но если вы хотите экспортировать их по любой причине, и они не появляются, не выполняйте bash
после export
, а скорее bash –norc
.
$PATH
это среда, которую пользователи обычно меняют больше всего.
Если мы 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 для 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) проходят ** под прикрытиями.