Переменные окружения играют ключевую роль в работе операционной системы Linux, позволяя передавать конфигурационные данные и временные значения между процессами. Они используются для настройки поведения системы и приложений, а также для хранения информации, необходимой для работы программ и доступа к ресурсам.
По сути, переменные окружения представляют собой именованные значения (также известные как пары «ключ-значение») и могут содержать такие важные данные, как пути к директориям и исполняемым файлам, язык и часовой пояс, значения по умолчанию для различных приложений и многое другое. Часть переменных хранится в файлах конфигурации, часть может быть задана пользовательским вводом или приложением.
Отличие переменных окружения от переменных оболочки
Окружением мы будем называть область памяти, в которой оболочка хранит все переменные, необходимые для взаимодействия программ.
Переменные окружения (Environment Variables) доступны всем процессам, запущенным внутри одной сессии оболочки, и могут быть созданы, изменены и удалены. Заметим, что сессия может быть запущена как во время локального входа через терминал или графический интерфейс, так и во время удалённого подключения, например, через SSH.
Другими словами, переменные окружения используются для передачи данных в процессы, порождаемые оболочкой.
Переменные оболочки (Shell Variables), в отличие от переменных окружения, доступны только в той оболочке, в которой они были заданы. Хорошим примером такой переменной может служить локальная переменная PWD (present working directory, текущий рабочий каталог), то есть та папка, в которой находится текущий пользователь или исполняемый сценарий. Очевидно, что передавать такие локальные данные другим процессам не имеет смысла.
Давайте ещё раз подчеркнём различия между этими видами переменных:
- Область видимости. Переменные окружения доступны глобально всем дочерним процессам, тогда как переменные оболочки локальны для текущего сеанса.
- Наследование. Дочерние процессы наследуют переменные окружения и позволяют их переписывать, но не наследуют переменные оболочки.
Следует обратить особое внимание, что аккуратное обращение с переменными в глобальной области видимости имеет большое значение для обеспечения информационной безопасности системы.
Переменные окружения
В операционной системе может быть довольно много переменных окружения. Вывести полный список можно командами env
или printenv
. Разбить длинные списки на страницы позволяют команды less
или more
:

Здесь мы можем увидеть, в числе прочих, такие типовые переменные:
- PATH: список директорий, в которых система ищет исполняемые файлы.
- HOME: путь к домашнему каталогу текущего (активного) пользователя.
- USER и LOGNAME: имя логин текущего пользователя.
- SHELL: путь к текущей оболочке (командный интерпретатор по умолчанию).
- LANG: текущий язык и настройки локализации.
- EDITOR: консольный текстовый редактор по умолчанию для текущего пользователя.
- MAIL: путь к директории, в которой хранятся файлы входящей электронной почты текущего пользователя.
- UID: идентификатор активного аккаунта.
Обратите внимание, что в именах переменных используются заглавные буквы, а некоторые переменные содержат несколько значений, разделённых двоеточиями, например:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Переменные оболочки
Теперь давайте создадим тестовую переменную оболочки FIRST_VAR и исследуем её поведение.
FIRST_VAR="Hello, FirstVDS!"
Заметьте, что значение переменной содержит пробел, поэтому мы указали его в кавычках.
Вывести на экран созданную переменную можно командой echo
$ИМЯ_ПЕРЕМЕННОЙ (обратите внимание на знак доллара перед названием переменной):

Все переменные оболочки выводит команда set
:

Конечно, мы также можем вывести нашу переменную, совместно используя команды set
и grep
:

Установка и удаление переменных окружения
Сделать переменную FIRST_VAR доступной другим процессам можно с помощью команды export
:
export FIRST_VAR="Hello, FirstVDS!"
Теперь наша переменная доступна в глобальной области видимости, и мы можем её распечатать, например, командой «printenv | grep FIRST_VAR
»:

Удалить переменную из окружения можно командой «export -n FIRST_VAR
». После этого она будет отсутствовать в глобальной области видимости, но всё ещё будет видна в переменных оболочки по команде echo
:

Удалить переменную полностью можно командой unset
:
unset FIRST_VAR
Также в качестве альтернативы можно просто очистить значение переменной, записав в неё пустое значение:
FIRST_VAR=
Изменение переменных окружения
На практике довольно часто возникает необходимость изменить некоторые переменные окружения, например, добавить дополнительный путь к списку PATH. Сделать это можно такой командой:
export PATH=$PATH:/<абсолютный путь к исполняемому файлу или папке>
Например, после установки виртуальной машины Java JRE или JDK можно задать домашнюю директорию JAVA_HOME и добавить исполняемые файлы Java к существующим путям PATH:
export JAVA_HOME="<путь к java>"
export PATH=$PATH:$JAVA_HOME/bin
В этом примере путь к папке $JAVA_HOME/bin добавлен в конец списка PATH после двоеточия.
Настройка переменных окружения и оболочки во время входа
Обратите внимание, что приведённые выше переменные, установленные командой export из терминала, будут действовать только в текущем сеансе. Чтобы сделать переменную окружения постоянной, вы можете добавить её в файл конфигурации оболочки, например, в ~/.bashrc или ~/.bash_profile для текущего пользователя:
echo 'export FIRST_VAR="Hello, FirstVDS!"' >> ~/.bashrc
Теперь переменная FIRST_VAR будет доступна после перезагрузки компьютера или во время запуска нового сеанса. Чтобы сделать её активной немедленно, можно выполнить команду:
source ~/.bashrc
Постоянные переменные окружения для всех пользователей и процессов могут располагаться в файлах конфигурации /etc/profile, /etc/bash.bashrc или /etc/environment в зависимости от типа инициализации сеанса (например, локальное подключение или удалённая SSH-сессия, интерактивный запуск через терминал или вызов из приложения, наличие или отсутствие логина). Подробнее о файлах инициализации оболочки можно узнать в официальной документации по bash.
Обратите внимание, что вы не можете напрямую читать переменные другого пользователя или другой оболочки. Если вы запустите новую оболочку, она получит собственную копию переменных родителя.
Примеры использования переменных при запуске контейнеризированных приложений
Как известно, контейнеры, такие как Docker, позволяют запускать приложения в изолированной среде. Давайте рассмотрим конкретный пример и проверим, насколько изолированы области видимости переменных окружения.
Будем считать, что Docker уже установлен в нашей операционной системе. Проверить это можно командой «systemctl status docker
»:

Если у вас нет строк «Loaded: loaded» и «Active: active», можно воспользоваться инструкцией с официального сайта или установить службу, используя пакетный менеджер вашего дистрибутива. Например, для Debian достаточно выполнить команду:
sudo apt install docker.io
Установим тестовый образ hello-world командой «docker pull hello-world
» и запустим его с помощью «docker run hello-world»
:

После этого можно, например, запустить контейнер ubuntu, рекомендованный в выводе предыдущей команды:
docker run -it ubuntu bash
Передать переменные окружения в этот контейнер можно, например, добавив параметр «--env SECOND_VAR=Hello!». Полностью команда будет выглядеть так:
docker run -it --env SECOND_VAR="Hello!" ubuntu bash
Теперь давайте выведем переменные окружения, доступные внутри контейнера, с помощью команды env
:

Как видите, переменная окружения SECOND_VAR доступна, а FIRST_VAR — нет.
Такой же результат можно получить, выполнив в соседнем терминале команду «docker exec <container_id> bash -c printenv»
:

Идентификатор запущенного контейнера (container_id) можно увидеть в приглашении оболочки после знака @ или выполнив команду «docker container ls»
.
Конечно, использованный в этом примере способ передачи переменных в контейнер далеко не единственный. Вы также можете, например, указать альтернативный файл с переменными окружения с помощью параметра «--env-file путь/к/файлу» или добавить в Dockerfile инструкцию «ENV имя_переменной="значение_переменной"», а если вы используете утилиту docker-compose, то нужные аргументы можно добавить в конфигурационный файл docker-compose.yml.
С точки зрения безопасности данных в приведённом примере всё нормально —в выводе нет глобальных переменных, например, FIRST_VAR. Но обратите внимание, что переменную SECOND_VAR мы передали в контейнер в открытом виде. Это означает, что хотя контейнеры действительно являются отличным средством изоляции приложений, полагаться на них в качестве средства обеспечения информационной безопасности не стоит. Кроме того, важно отметить, что даже если передаваемые параметры определяются в локальной среде или в файлах, они могут содержать чувствительную информацию, например, пароли от баз данных или данные авторизации внешних служб, что заставляет администраторов принимать дополнительные меры по защите конфиденциальности.
Заключение
Переменные окружения и переменные оболочки — мощные инструменты для настройки среды выполнения в Linux, позволяющие эффективно управлять конфигурацией и взаимодействием служб. Они дают возможность легко изменять поведение системных команд и приложений, обеспечивая гибкость и удобство работы. Кроме того, механизм переменных позволяет отделить программы от их конфигурации, благодаря чему можно значительно улучшить повторяемость и масштабируемость кода.
Но следует помнить, что с большими возможностями приходит большая ответственность, и внимательно относиться к вопросам безопасности при использовании переменных окружения.