Что именно является переменной среды?


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представляет собой массив строк, обычно в форме ключ = значение, которые передаются в качестве среды для новой программы.

environ(7)Страница руководства также предлагает некоторое представление:

СИНТАКСИС

   extern char **environ;

ОПИСАНИЕ

Переменная environуказывает на массив указателей на строки, называемые «окружением». Последний указатель в этом массиве имеет значение NULL. (Эта переменная должна быть объявлена ​​в пользовательской программе, но объявлена ​​в заголовочном файле <unistd.h>в случае, если заголовочные файлы были получены из libc4 или libc5, и если они пришли из glibc, и был определен _GNU_SOURCE.) Этот массив строк сделан доступным для процесс с помощью вызова exec (3), который запустил процесс.

Обе эти страницы руководства GNU соответствуют спецификации POSIX


4
+1, вероятно, стоит отметить, что некоторые члены exec(3)семьи (т.е. те, которые не соответствуют exec * v) проходят ** под прикрытиями.
2011 г.

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

@msw: это exec*eварианты, которые явно передают env вместо неявного использования environглобальной переменной. Значение v«вектор» и относится к аргументам командной строки, передаваемым в виде массива (а не «списка» (функция переменной длины)), execveявляется системным вызовом, а все остальные exec*функции являются для него оболочками libc.
Питер Кордес

19

Вы ошибаетесь: 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-программы, например, наследуют много информации от веб-сервера через переменные среды.


1
Казалось бы, все еще немного сложнее. По крайней мере, в bash SOME_NAME=value commandбудет установлена ​​переменная окружения SOME_NAME для вызова этой команды. Забавно, но, похоже, переменная оболочки не имеет того же имени.
Сэмюэль Эдвин Уорд

2
Точнее, переменные окружения не наследуются, а явно передаются из оболочки в программы, которые она порождает.
MSP

2
@SamuelEdwinWard причина, по которой вы ведете SOME_NAME=value commandсебя вопреки вашим ожиданиям, заключается в том, что это специальный синтаксис, означающий «добавьте SOME_NAME в среду, переданную команде, но не изменяйте иные переменные этой оболочки».
MSP

1
Увлекательная, ссылка на лямбда-исчисление / функциональное программирование. Это интересная связь, которая имеет большой смысл.
Мэтт

1
Отчасти это не совсем верно. Например, Подоболочки являются подпроцессами и должны быть fork()эд, но они делают получить (копию) переменную оболочки.
Руах

7

Переменные окружения в их исходной форме - это просто набор пар имя / значение. Как описано в 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).

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


0

«Переменные среды» - это набор динамических именованных значений, которые могут влиять на поведение запущенных процессов на компьютере.

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

Более подробная информация здесь → http://en.wikipedia.org/wiki/Environment_variable .

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


1
Хотя вряд ли эти ссылки исчезнут, лучше ответить на вопрос здесь соответствующим текстом и предоставить ссылку в качестве дополнения для информации о резервном копировании.
Антон

@Антон Я верю, что ты прав, и я внесу изменения, как только смогу ... Спасибо за совет ...
SoCalDiegoRob

-1

Этот ответ требует некоторого опыта и знаний сценариев оболочки с терминами переменная, значение, подстановка переменной, приглашение, эхо, ядро, оболочка, утилита, сеанс и процесс.

Переменная окружения (envar) представляет собой набор глобальных определенных переменных , которые могут повлиять на то , как данные процессы будут вести себя в операционной системе компьютера.

1. Примерное введение:

Мы заменяем 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в терминале и взглянуть на вывод.

2. Как эти данные отображаются и обрабатываются:

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

Вышеуказанные изменения обычно носят временный характер, и вот почему:

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

Изменения, которые мы вносим в один процесс, уникальны для него и прекратятся, если мы закроем его, не сохранив их каким-либо образом.

Итак, как мы можем сохранить эти изменения:

Существует несколько типов способов хранения изменений envar в зависимости от выбранной области. Вот разные области (уровни) для таких изменений:

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

Где хранятся данные envar:

Unix состоит из 3 основных уровней: ядра, оболочки и утилит. AFAIK каждая оболочка имеет свои собственные envars, и они построены в основном или исключительно в оболочке.

Конкретное место, где можно глобально изменить их, обычно, /etc/profileхотя мы также можем сделать это, .bashrcконечно.

3. Создание новых envars:

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

MESSAGE="Hello world!"

создаст его для нас, и теперь, если мы введем echo $MESSAGE, мы получим hello world!.

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

Примечание. В операционных системах с эмулятором терминала (например, рабочим столом Ubuntu) субсессия обычно выполняется в том же окне, но новый сеанс в другом окне не является субсессией существующего (это смежный процесс). ,

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

Экспорт envar из исходного сеанса во все подсессии:

Мы по-прежнему можем использовать envar, созданный в первом сеансе, а также во втором сеансе, без регистрации его в пользовательских файлах или файлах глобального уровня (см. Следующие данные). Вот как это сделать:

Перейти к исходному сеансу (в текущем или другом окне) и выполнить:

export MESSAGE

при экспорте не используйте $знак.

Теперь он экспортируется во все подсессии. Если вы будете выполнять echo $MESSAGEв подсессии, от вашего пользователя или другого, он будет напечатан.

Обратите внимание, что внутренние переменные оболочки, такие как, PS1не должны экспортироваться, но если вы хотите экспортировать их по любой причине, и они не появляются, не выполняйте bashпосле export, а скорее bash –norc.

4. Envar $ PATH:

$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сокращенно как ~.

Отношения system- $ PATH и возможное взаимодействие с пользователем:

В Bash 4.xx, когда мы используем утилиту без полного пути, система будет использовать все 6 упомянутых выше значений $PATHenvar. Итак, он будет начинаться с /user/local/binи будет следить за всем своим содержимым в поисках echoисполняемого файла.

В этом случае он остановится на том /bin/echo, в котором, в этом случае, находится исполняемый файл.

Следовательно, основная причина, по которой мы могли бы настроить $PATHenvar, - это установка исполняемых файлов, которые не соответствуют ни одному из его собственных значений.

После установки таких исполняемых файлов мы должны соответствующим образом установить их $PATHзначение, и тогда мы сможем работать с ними.

5. Приложение - расширение $PATH:

Мы можем export $PATHобъединить подсессии (включая расширения bash, такие как WP-CLI для WordPress или Drush для 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.