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 • Окружение • Переменная