Шаг 17 - Работа с переменными окружения - setenv и getenv

Раньше мы познакомились с тем, как получать параметры в программе с помощью семейства функций getopt (подробнее читайте "Шаг 10 - Передача опций в программу - getopt" и "Шаг 11 - Передача длинных опций в программу - getopt_long"). Но существует еще один метод - переменные окружения или переменные среды. С ними мы успели уже познакомиться раньше в шаге "Шаг 13 - Получение информации о пользователе". С помощью данных переменных можно передавать в программу дополнительные специфические параметры, которые могут использоваться несколькими программами одновременно и они характеризуют "среду", в которой выполняется программа.

Например, если Вы разрабатываете какую-то систему состоящую из нескольких программ работающих независимо, то к примеру, Вы захотите сообщить всем программам рабочий каталог, временную директорию или какой-нибудь другой специфичный параметр. Тогда переменные окружения, это единственный разумный метод, ведь передавать такие параметры через командную строку глупо. Почему ?! Ну, например, приведу скрипт запуска какой-нибудь сложной системы:

#!/bin/bash

/yoyosystem/cheduler --time=60 --work-dir=/yoyosystem/data --temp-dir=/tmp/yoyosystem
/yoyosystem/counter -c 25 -w 31 --work-dir=/yoyosystem/data --temp-dir=/tmp/yoyosystem
/yoyosystem/pusher --stack-size=512 -m 12 --work-dir=/yoyosystem/data --temp-dir=/tmp/yoyosystem

Ну, как ?! Громодко ! А вот как более красиво:

#!/bin/bash

export YOYO_WORK_DIR="/yoyosystem/data"
export YOYO_TEMP_DIR="/tmp/yoyosystem"

/yoyosystem/cheduler --time=60
/yoyosystem/counter -c 25 -w 31
/yoyosystem/pusher --stack-size=512 -m 12

Каждая из указанных программ будет брать параметры об используемых директориях из переменных среды YOYO_WORK_DIR и YOYO_TEMP_DIR, что значительно упрощает написание и модификацию скрипта запуска системы, а также убережет от опечаток и связанных с этим ошибок. Поэтому переменные среды достаточно важны и Вы всегда должны помнить об их удобстве.

А теперь собственно давайте познакомимся с этими переменными среды. Библиотека glibc предоставляет весь спектр функций для работы с ними в заголовочном файле stdlib.h.

Сначала познакомимся с самим массивом переменных окружения, который определен в заголовочном файле unistd.h в таком виде:

/* NULL-terminated array of "NAME=VALUE" environment variables.  */
extern char **__environ;
#ifdef __USE_GNU
extern char **environ;
#endif

Представлет собой массив указателей на строки формата "имя=значение" и заканчивается нулевым указателем NULL. Давайте попробуем написать программу вывода всех переменных:

#include <stdlib.h>
#include <unistd.h>

int main(int argc,char **argv) {
    int i=0;

    while (__environ[i] != NULL) {
        printf("%s\n",__environ[i]);
        i++;
    };
    return 0;
};

Данная программа выведет весь список переменных среды окружения, которые доступны программе:

root@darkstar:/@@@@@@# ./a.out
MANPATH=/usr/local/man:/usr/man:/usr/X11R6/man:/usr/lib/java/man
HOSTNAME=darkstar.example.net
SHELL=/bin/bash
TERM=xterm
USER=root
MC_TMPDIR=/tmp/mc-root
T1LIB_CONFIG=/usr/share/t1lib/t1lib.config
MINICOM=-c on
PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:
MAIL=/var/mail/root
LC_COLLATE=C
PWD=/@@@@@@
INPUTRC=/etc/inputrc
JAVA_HOME=/usr/lib/java
LANG=en_US
PS1=\u@\h:\w\$
HISTCONTROL=ignorespace
PS2=>
HOME=/root
SHLVL=2
LOGNAME=root
LESS=-M
LESSOPEN=|lesspipe.sh %s
OLDPWD=/usr/include
_=./a.out

Я конечно вырезал некоторые переменные, которые слишком большие, но все равно достаточно информативно и можно считать, что программа знает о среде в которой запущена практически все.

Для доступа к переменным окружения, есть несколько функций:

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

#include <stdlib.h>

int main(int argc,char **argv) {
    char *HOME = getenv("HOME");
    char *USER = getenv("USER");

    printf("Home directory: \"%s\"\n",HOME);
    printf("User name: \"%s\"\n",USER);

    return 0;
};

При вызове данной программы вы узнаете свой домашний каталог и имя пользователя. Например:

root@darkstar:/@@@@@@# ./a.out
Home directory: "/root"
User name: "root"

Использование переменных окружения полезно не только, когда Вам требуется настроить в нескольких программах какие-то параметры, но и для обмена данными между процессами. То есть в одной программе Вы создаете переменную, а в другой получаете значение этой переменной. Таким образом можно наладить обмен простыми короткими данными между процессами. Но, конечно, все-таки не стоит сильно злоупотреблять этой возможностью :)


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Кузин Андрей.