2010-08-05 8 views
28

Есть ли способ установить переменные среды в Linux с помощью C?Установить переменные среды в C

Я попробовал setenv() и putenv(), но они, похоже, не работают для меня.

+0

Почему, на ваш взгляд, они не работают? (То есть, как вы это протестировали? Getenv?) –

+0

Не могли бы вы разместить образец кода и демонстрацию, показывающую, как они не работают? – FrustratedWithFormsDesigner

ответ

44

Я собираюсь сделать здесь дикое предположение, но нормальная причина, по которой эти функции не работают, заключается не в том, что они не работают, а потому, что пользователь действительно не понимает, как работают переменные среды. Например, если у меня есть эта программа:

int main(int argc, char **argv) 
{ 
    putenv("SomeVariable=SomeValue"); 
    return 0; 
} 

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

+0

Следствием этого является получение поведения «запуска программы для установки переменных» в оболочке: 1) написать сценарий оболочки для выполнения задания и 2) не запускать его обычным способом, а скорее «source». (BTW в большинстве оболочек '. Script' - это то же самое, что и« исходный скрипт »и намного меньше набрав.) – dmckee

+0

Это имеет большой смысл, спасибо :) Да, это было то, что я делал. Я новичок в Linux, так что простите меня, если это глупый вопрос, но нет никакого способа, чтобы дочерний процесс устанавливал среду оболочек в C и не использовал сценарий. Я работаю в этой компании, и меня попросили написать функцию для установки часового пояса устройства, использующего linux, поэтому я пытался установить среду TZ оболочки. – iman453

+0

@iman: попробуйте 'man -k tz' для некоторых опций. На моей машине Mac OS X появилось сообщение 'tzset (3)' ... – dmckee

5

Переменная окружения, заданная setenv()/putenv(), будет установлена ​​для процесса, выполняющего эти функции и наследуемого процессами, запущенными им. Тем не менее, это не будет ввело в оболочку, которая выполнила вашу программу.

Why isn't my wrapper around setenv() working?

1

Блок окружающей среды является процесс локального, и копируются в дочерние процессы. Поэтому, если вы меняете переменные, новое значение влияет только на процесс и дочерние процессы, возникшие после изменения. Разумеется, он не изменит оболочку, с которой вы начали.

-2

Я получил его от моего "Advanced Programming in the UNIX Environment" книга.

Окружающая среда перечисляет массив указателей на фактические строки с именем = значение, а строки среды обычно хранятся в верхней части пространства процесса процесса над стеком.

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

  1. Если вы изменяете существующее имя:

    а. Если размер нового значения меньше или равен размеру существующего значения, мы можем просто скопировать новую строку поверх старой строки.

    b. Если размер нового значения больше старого, мы должны malloc получить место для новой строки, скопировать новую строку в эту область, а затем заменить старый указатель в списке окружения на имя с помощью указатель на эту выделенную область.

  2. Если мы добавляем новое имя, это сложнее. Во-первых, мы должны вызвать malloc, чтобы выделить место для строки name = value и скопировать строку в эту область.

    a. Затем, если мы впервые добавили новое имя, мы должны вызвать malloc, чтобы получить место для нового списка указателей.Мы копируем старый список среды в эту новую область и сохраняем указатель на строку name = value в конце этого списка указателей. Разумеется, мы также сохраняем нулевой указатель в конце этого списка. Наконец, мы устанавливаем окружение, чтобы указать на этот новый список указателей. если исходный список окружения содержался выше вершины стека, как это обычно бывает, мы переместили этот список указателей в кучу. Но большинство указателей в этом списке по-прежнему указывают на строки с именем = value над вершиной стека.

    b. Если мы не добавили новые строки в список окружения, то мы знаем, что мы уже выделили место для списка в куче, поэтому мы просто вызываем realloc, чтобы выделить место для еще одного указателя. Указатель на новую строку name = value сохраняется в конце списка (поверх предыдущего нулевого указателя), за которым следует нулевой указатель.

Все самое лучшее.

+0

Я не уверен, что вы поняли вопрос OP ... – dmckee

+0

Вы правы :-). Мое понимание заключалось в том, что он сталкивается с некоторыми в своем исполняемом файле после установки переменных env. – Hemant

9

Любая программа unix запускается в отдельном процессе процесса, который запускает его; это «детский» процесс.

Когда программа запускается - будь то в командной строке или любым другим способом - система создает новый процесс, который является (более или менее) копией родительского процесса. Эта копия включает переменные среды в родительском процессе, и это механизм, посредством которого дочерний процесс «наследует» переменные среды родителя. (Все это в значительной степени то, что другие ответы здесь уже говорили)

То есть, процесс только когда устанавливает свои собственные переменные окружения.

Другие упомянули поиск сценария оболочки как способ задания переменных среды в текущем процессе, но если вам необходимо программно установить переменные в текущем (оболочном) процессе, то есть несколько косвенный способ, которым это возможно ,

Рассмотрим это:

% cat envs.c 
#include <stdio.h> 
int main(int argc, char**argv) 
{ 
    int i; 
    for (i=1; i<argc; i++) { 
     printf("ENV%d=%s\n", i, argv[i]); 
    } 
} 
% echo $ENV1 

% ./envs one two 
ENV1=one 
ENV2=two 
% eval `./envs one two` 
% echo $ENV1 
one 
% 

Встроенный eval оценивает свой аргумент, как если бы этот аргумент был набран в командной строке. Это пример sh-стиля; вариант csh-стиля остается в виде упражнения!

+0

Я заметил, что это было отклонено. Любое указание почему? Кто-то заметил ошибку? –

+0

Не знаете, почему кто-то мог бы понизить это. Weird. Похоже, хорошее решение для меня! – wasatchwizard

+0

Я полагаю, это связано с тем, что ответ задает переменную окружения, используя встроенную команду bash 'eval', которые являются шансами, что программист вообще не сможет использовать bash. Если программисту разрешено использовать сценарий оболочки (что не всегда так, следовательно, вопрос), есть и другие более очевидные и более эффективные способы установки переменной среды, отличной от специфической оценки bash. (стр. Я не спускал вниз) –

Смежные вопросы