7.2. Определение просмотр и изменение переменных окружения

Описание:  Кандидат BSDA должен уметь просматривать и изменять переменные окружения временно и постоянно для любой оболочки поставляемой с системой BSD.

Практика: env(1), sh(1), csh(1), tcsh(1), environ(7)

Комментарий

Многие программы в UNIX берут настроечную информацию из переменных окружения. Это хороший способ передать в программу информацию, общую для разных программ. Например программа df(1) будучи вызвана без аргументов выводит информацию о свободном месте в единицах заданных в переменной BLOCKSIZE. Другие программы (du(1), ls(1)) берут эту же информацию из этой же переменной. Не будь механизма с переменными окружения, нам понадобился бы некоторый общий реестр с переменными, в котором скорее всего царил бы полный хаос.

Ниже приведён некоторый список переменных влияющих на поведение разнообразных программ и их значение. Список приведён по данным страницы man environ(7).

Таблица 7.1. Пользовательске переменные окружения [environ(7)]

ПеременнаяОписание
BLOCKSIZE Размер блока используемый некоторыми командами, в частности df(1), du(1) и ls(1). BLOCKSIZE может быть указан в байтах, а может в килобайтах, мегабайтах или гигабайтах, если указать суффикс K, k, M, m, G или g. величины менее 512 или более 1G игнорируются
COLUMNS Предпочитаемая пользователем ширина вывода для терминала. Используется такими утилитами, как ls(1) и who(1) для форматирования вывода на терминал. Если переменная неустановлена или пуста утилиты используют вызов ioctl(2) чтобы выяснить ширину терминала.
EDITOR Имя текстового редактора по умолчанию
EXINIT Список команд выполняемых при старте ex(1) и vi(1).
HOME Пользовательский каталог. Устанавливается login(1) из файла passwd(5).
LANG Локаль. Эта переменная влияет на все программы использующие вызов setlocale(3).
LC_ALL Локаль. Переписывает значение переменных LC_COLLATE, LC_CTYPE, LC_MESSAGES, LC_MONETARY, LC_NUMERIC и LC_TIME.
LC_COLLATE Локаль. Сортировка строк.
LC_CTYPE Переменная для определения того, какие символы являются буквой, пробелом, цифрой и т.п. в данной локали. Какой порядок байт принят в локали.
LC_MESSAGES Локаль для диагностических сообщений
LC_MONETARY Локаль для указания формата валют.
LC_NUMERIC Локаль для отображения чисел
LC_TIME Локаль для отображения дат
MAIL Расположение почтового ящика пользователя (вместо используемого по умолчанию /var/mail), используется mail(1), sh(1) и многими другими почтовыми клиентами.
NLSPATH Список каталогов используемых для поиска сообщений диагностических сообщений LC_MESSAGES. См. catopen(3).
PAGER Название используемой по умолчанию программы-пейджера для постраничного вывода на экран (например less). Переменная используется mail(1), man(1), ftp(1), для вывода на экран сообщений неумещающихся на экран.
PATH Список каталогов разделённых двоеточием, в которых осуществляется поиск исполнимых файлов программами csh(1), sh(1), system(3), execvp(3), и пр.
PRINTER Имя используемого по умолчанию принтера для программ lpr(1), lpq(1), и lprm(1).
PWD Текущий рабочий каталог
SHELL Полный путь к пользовательской оболочке
TERM Имя текущего терминала. Используется командами nroff(1) или plot(1) для определения функциональности терминала. Полный список типов терминалов приведён в файле /usr/share/misc/termcap (termcap(5)).
TERMCAP Строка описывающая терминал или, если начинается со '/' — имя файла termcap. См. TERMPATH ниже и termcap(5)
TERMPATH перечень файлов termcap разделённых двоеточием или пробелом, в которых ищется описание терминала. Отсутствие TERMPATH эквивалентно наличию переменной TERMPATH равной $HOME/.termcap:/etc/termcap. TERMPATH неиспользуется, если TERMCAP содржит полный путь к файлу.
TMPDIR Каталог для хранения временных файлов. Большинство приложений используют /tmp или /var/tmp. Установка этой переменной может заставить их использовать другое место.
TZ Часовой пояс (timezone) для отображения дат. указывает путь относительно каталога /usr/share/zoneinfo. Напимер, чтобы узнать сколько времени в Москве env TZ=Europe/Moscow date, в Иркутске — env TZ=Asia/Irkuts date См. также tzset(3).
USER Имя пользователя (логин).

7.2.1. Просмотр и изменение переменных окружения

7.2.1.1. env(1), printenv(1)

Утилита env нужна для просмотра текущих переменных окружения и/или запуска программ в специфическом окружении. Будучи вызвана без аргументов она печатает список текущих переменных и их значения. Можно задать команде env список переменных и их значения и команду. Тогда эта команда будет выполнена с указанными переменными. Опция -i может применяться для того, чтобы env(1) не наследовала уже заданных переменных. Чтобы узнать значение конкретной переменной можно так же использовать команду printenv(1). Например:

$ env | grep TZ
TZ=Europe/Moscow
$ date
среда, 15 февраля 2006 г. 22:14:28 (MSK)
$ env TZ=Asia/Irkutsk date
четверг, 16 февраля 2006 г. 03:14:38 (IRKT)
$ date
среда, 15 февраля 2006 г. 22:14:41 (MSK)
$ printenv TZ
Europe/Moscow
   

Есть распространённая практика писать утилиту env(1) в «магичекую строку» (shebang), с которой обычно начинаются сценарии:

#!/usr/bin/env python
   

Таким способом программисты страхуются от того, что интерпретатор python(1) может находиться в неправильном месте. Так, в FreeBSD, DragonFly BSD и OpenBSD python(1) будет скорее всего установлен в каталог /usr/local/bin, в NetBSD в /usr/pkg/bin, в Linux он возможно будет стоять в /usr/bin. Чтобы магическая строка всегда работала нужно либо переписывать её при инсталляции скрипта (Обычно инсталляторы так и желают), либо писать как выше в расчёте на то, что путь к языку python(1) у пользователя прописан в переменной PATH.

Такой подход по ряду причин надо признать крайне неудачным. Во-первых, такой скрипт будет работать не всегда. Будучи вызван из crontab он может работать в ситуации, когда переменная PATH вообще не задана. Кроме того, влияя на переменную PATH пользователь может подсунуть поддельный интерпретатор. Если вы выдали недобросовесному судоеру права на запуск утилиты /root/bin/util.py с правами root, а в утилите в магической строке python(1) вызывается через env(1), то судоер может переопределив PATH подсунуть поддельный python и получить полный контроль над системой.

С другой стороны, прежде чем выдавать права суперпользователя на исполнения некоторого скрипта, надо хорошо понимать как работает интерпретатор, который вы используете. Рассмотрим пример с тем же python(1). Пусть у нас есть скрипт hello.py такого содержания:

#!/usr/local/bin/python
print "Hello World!"
   

Запустив этот скрипт командой

$ sudo env PYTHONINSPECT="1" ./test.py
Hello World
>>>
   

судоер по завершении скрипта получит приглашение командной строки интерпретатора python(1) через которую он получит полную власть над системой. Чтобы избежать этого, надо либо явно указать в скрипте инструкцию выхода:

#!/usr/local/bin/python
import sys
print "Hello World!"
sys.exit()
   

либо ограничить пользователя в использовании переменных окружения:

#!/usr/bin/env -i /usr/local/bin/python
print "Hello World!"
   

7.2.1.2. sh(1), export

В интерпретаторе sh можно задать значение переменной путём присваивания: var=value, например NEW=1. После этого переменную можно использовать, на её значение можно ссылаться из по имени $NEW, но она ещё не стала переменной окружения. Чтобы эта переменная стала видна программе как переменная окружения, её надо экспортировать командой export.

$ NEW=1
$ echo $NEW
1
$ printenv NEW
$ export NEW
$ printenv NEW
1
   

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

Полный список переменных можно узнать командой set без аргументов, а список экспортированных переменных командой export без аргументов.

7.2.2. csh(1), set, setenv

В языке csh переменная устанавливается командой set, а переменная окружения командой setenv. Причём переменные и переменные окружения это два совершенно разных массива. Может быть одновременно определена переменная и переменная окружения с тем же именем, но другим значнием:

% set NEW=1
% printenv NEW
% echo $NEW
1
$ setenv NEW 2
$ printenv NEW
2
$ echo $NEW
1
  

Обратите внимание: команды set и setenv имеют разный синтаксис.


Обновлено: 12.03.2015