Linux. Переменные окружения и оболочки
Каждый раз, когда активируется сессия оболочки, запускается процесс для сбора и компиляции информации, которая должна быть доступна оболочке и ее дочерним процессам. Оболочка получает эти данные от множества различных файлов и настроек в системе.
Среда содержит множество пар типа «ключ-значение». Если ключ содержит несколько значений, они обычно разделяются двоеточием. Если значение ключа содержит пробелы — нужно использовать кавычки.
КЛЮЧ_РАЗ=значение КЛЮЧ_ДВА=значение1:значение2:… КЛЮЧ_ТРИ='значение с пробелами'
В данном случае под ключом подразумеваются переменные одного из двух существующих видов: переменные окружения или переменные оболочки.
Переменные окружения — это переменные, которые были определены для текущей оболочки и наследуются всеми дочерними оболочками или процессами. Переменные окружения используются для передачи информации процессам, запущенным из оболочки.
Переменные оболочки — это локальные переменные, которые содержатся исключительно в оболочке, в которой они были установлены или определены. Они часто используются для отслеживания текущих данных (к примеру, текущего рабочего каталога).
Обычно такие переменные обозначаются с помощью заглавных букв. Это помогает пользователям различать переменные окружения в других контекстах.
Вывод переменных оболочки и окружения
Для просмотра списка всех переменных окружения, используются команды env
или printenv
. По умолчанию они выведут точно такой же результат:
$ env SHELL=/bin/bash USER=evgeniy PWD=/home/evgeniy LANG=ru_RU.UTF-8 ..........
Данные команды отличаются только несколькими индивидуальными функциями. К примеру, printenv
может запрашивать значения отдельных переменных:
$ printenv SHELL /bin/bash
Команда env
позволяет изменять окружение, в которой запущена программа, передавая набор определений переменных в команду, примерно так:
$ env VAR='some value' command options
Как сказано выше, дочерние процессы наследуют переменные окружения родительского процесса, что дает возможность менять значения или вносить дополнительные переменные для дочерних процессов.
Как можно видеть в выводе команды env
, многие переменные окружения созданы с помощью системных файлов и процессов без вмешательства пользователя.
Для просмотра переменных оболочки можно использовать команду set
. Но, при вводе без дополнительных параметров, set
выводит список всех переменных оболочки, переменных окружения, локальных переменных и функций оболочки.
Этот список содержит огромное количество дополнительной информации, которая нам в данный момент не интересна (к примеру, некоторые функции bash).
Основные переменные окружения и оболочки
Некоторые особенно полезные переменные окружения и оболочки используются очень часто. Ниже приведен список основных переменных окружения:
SHELL
: описывает оболочку, которая интерпретирует введенные команды. В большинстве случаев по умолчанию установлена bash, но это значение можно изменить в случае необходимости.TERM
: указывает вид терминала, эмулируемого при запуске оболочки. В зависимости от операционных требований можно эмулировать разные аппаратные терминалы.USER
: текущий пользователь.PWD
: текущий рабочий каталог.OLDPWD
: предыдущий рабочий каталог. Оболочка хранит его на случай запуска командыcd -
.LS_COLORS
: определяет цветовые коды, которые используются для цветного вывода результата команды ls. Такой вывод помогает пользователю быстрее прочесть результат команды (например, быстро различить типы файлов).MAIL
: путь к текущему почтовому ящику пользователя.PATH
: список каталогов, к которым обращается система при выполнении команд. Когда пользователь запускает команду, система проверяет эти каталоги в указанном порядке в поисках исполняемого файла.LANG
: текущие настройки языка и локализации, в том числе кодировка символов.HOME
: домашний каталог текущего пользователя._
: последняя выполненная команда.
Ознакомившись со списком переменных окружения, посмотрим на список переменных оболочки:
BASHOPTS
: список опций, использованных при выполнении bash. Это можно применять для того, чтоб проверить, работает ли окружение должным образом.BASH_VERSION
: запущенная версия bash в удобочитаемой форме.BASH_VERSINFO
: версия bash в машиночитаемом формате.COLUMNS
: определяет ширину вывода в столбцах.DIRSTACK
: стек каталогов, доступных командамpushd
иpopd
.HISTFILESIZE
: максимальное количество строк, содержащееся в файле истории команд.HISTSIZE
: Количество команд, которые необходимо запоминать в списке истории.HOSTNAME
: текущее имя хоста.IFS
: Внутренний разделитель полей ввода в командной строке. По умолчанию установлен пробел.PS1
: определяет строку первичного приглашения – вид командной строки при запуске сессии оболочки. ПеременнаяPS2
устанавливает строку вторичного приглашения, если команда занимает несколько строк.SHELLOPTS
: параметры оболочки, которые можно установить при помощиset
.UID
: уникальный идентификатор текущего пользователя.
Создание переменных оболочки
Это делается очень просто, для этого нужно только указать имя и значение. Как уже было сказано, для написания имен таких переменных используются заглавные буквы.
$ TEST_VAR='Hello World!'
В данном примере используются кавычки, поскольку значение содержит пробелы. Более того, здесь нужно использовать именно одинарные кавычки, так как восклицательный знак является специальным символом в bash-оболочке, который обращается к истории команд, если он не избегается или не заключен в одинарные кавычки.
Полученная переменная оболочки действительна в текущей сессии, но не передается ее дочерним процессам. Чтобы убедиться, что данная переменная не является переменной окружения, используем команду grep
для фильтрации вывода команды env
:
$ env | grep TEST_VAR $
Данное действие не выведет никакого результата.
Убедимся в том, что переменная TEST_VAR
не передается дочернему процессу. Для этого внутри текущей оболочки запустим новую оболочку:
$ bash $ echo $TEST_VAR $
Возвращаемся в исходную оболочку:
$ exit
Создание переменных окружения
Теперь попробуем превратить переменную оболочки в переменную окружения. Это делается путем экспорта переменной:
$ export TEST_VAR
Данная команда превращает переменную оболочки в переменную окружения. Чтобы проверить, все ли выполнено верно, можно снова просмотреть список переменных окружения:
$ env | grep TEST_VAR TEST_VAR=Hello World!
Можно также снова развернуть дочернюю оболочку:
$ bash $ echo $TEST_VAR Hello World!
Дочерняя оболочка получила переменную исходной оболочки. Попробуем экспортировать еще одну переменную, прежде чем покинуть дочернюю оболочку:
$ export NEW_VAR='New var value'
Проверим, экспортировалась ли переменная:
$ env | grep NEW_VAR NEW_VAR=New var value
Теперь вернемся в исходную оболочку:
$ exit
Проверим, можно ли открыть данную переменную:
$ echo $NEW_VAR $
Результат не возвращается. Это происходит потому, что переменные окружения передаются только дочерним процессам. Встроенного способа установки переменных окружения родительской оболочки нет. В большинстве случаев это предотвращает влияние программ на операционную среду, из которой они были запущены.
Переменная NEW_VAR
была установлена как переменная окружения дочерней оболочки. Эта переменная действительна для данной оболочки и ее дочерних оболочек и процессов. После возвращения пользователя в исходную оболочку — данная среда была разрушена.
Перемещение и сброс переменных
Переменная TEST_VAR
все еще является переменной окружения. Чтобы снова сделать ее переменной оболочки:
$ export -n TEST_VAR
Теперь эта переменная больше не является переменной окружения:
$ env | grep TEST_VAR $
Это снова переменная оболочки:
$ set | grep TEST_VAR TEST_VAR='Hello World!'
Чтобы полностью сбросить переменную, будь то переменная окружения или оболочки, надо использовать команду unset
:
$ unset TEST_VAR
Убедимся, что такой переменной больше нет:
$ echo $TEST_VAR $
Результат не был выведен, поскольку переменная была сброшена.
Какие бывают сеансы оболочки
Оболочка bash
считывает разные файлы конфигурации в зависимости от того, как запускается сеанс.
Первое отличие — запускается оболочка в рамках сеанса входа или без входа.
Оболочка входа — это сеанс оболочки, начинающийся с аутентификации пользователя. Если выполняется вход в сеанс терминала или через SSH с аутентификацией, сеанс оболочки будет настроен в виде оболочки со входом.
Если запускается новый сеанс оболочки внутри аутентифицированного сеанса (например, вызывая команду bash из терминала) — запускается сеанс оболочки без входа. При запуске дочерней оболочки не требуется вводить данные для аутентификации.
Второе отличие — является сеанс оболочки интерактивным или неинтерактивным. Интерактивный сеанс оболочки — это сеанс оболочки, прикрепленный к терминалу. Неинтерактивный сеанс оболочки не прикреплен к сеансу терминала.
Таким образом, каждый сеанс оболочки классифицируется либо как сеанс входа или без входа, либо как интерактивный или неинтерактивный.
Обычный сеанс, который начинается с SSH, как правило, представляет собой интерактивный сеанс входа. Скрипт, запускаемый из командной строки, обычно запускается в неинтерактивном сеансе без входа. Сеанс терминала может быть иметь любое сочетание этих двух параметров.
Сеанс, запускаемый в виде сеанса входа, будет считывать данные конфигурации сначала из файла /etc/profile
. Затем он считывает первый из файлов ~/.bash_profile
, ~/.bash_login
и ~/.profile
, который ему удается найти, и не считывает остальные файлы.
В отличие от этого сеанс, определенный в оболочке без входа, будет читать файл /etc/bash.bashrc
и затем использовать файл ~/.bashrc
конкретного пользователя для создания окружения.
Тут нужно учитывать, что /etc/profile
запускает на выполнение /etc/bash.bashrc
— так что не надо думать, что сеанс входа будет каким-то неполноценным, без инициализации bash. С другой стороны, сеансу без входа нет необходимости чтения /etc/profile
— потому что запускается внутри аутентифицированного сеанса и получит переменные окружения от него.
# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
if [ "${PS1-}" ]; then
if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
# The file bash.bashrc already sets the default PS1.
# PS1='\h:\w\$ '
if [ -f /etc/bash.bashrc ]; then
. /etc/bash.bashrc
fi
else
if [ "$(id -u)" -eq 0 ]; then
PS1='# '
else
PS1='$ '
fi
fi
fi
if [ -d /etc/profile.d ]; then
for i in /etc/profile.d/*.sh; do
if [ -r $i ]; then
. $i
fi
done
unset i
fi
Неинтерактивные оболочки считывают значение переменной окружения BASH_ENV
и указанный в нем файл для определения нового окружения, см. примеры здесь.
Переменные окружения пользователя
Чаще всего при настройке переменных окружения для конкретного пользователя — нужно чтобы эти переменные были доступны как в оболочке как со входом, так и в оболочке без входа. Это означает, что лучше всего использовать для определения переменных файл ~/.bashrc
.
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
В самом начале мы видим, что для неинтерактивной оболочки это файл не выполняется. Давайте еще заглянем в файл ~/.profile
— который выполняется для оболочки со входом. Этот файл тоже запускает на выполнение ~/.bashrc
.
# ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.
# if running bash
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
Если требуется задать общесистемные переменные, то их нужно добавлять в файлы /etc/profile
, /etc/bash.bashrc
или /etc/environment
.
Поиск: Bash • CLI • Linux • env • export • set • unset • Окружение • Переменная