На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила трёх "С"
Пожалуйста,
1. Соблюдайте правила Форума.
2. Слушайте советы Модераторов.
(например, http://forum.sources.ru/index.php?act=ST&f=7&t=80382 )
3. Сверяйтесь с учебником по Великому и Могучему
  
> Переменные в Shell
    В сишной пронрамме я пользуюсь функцией system();

    system('some_command'\nA=$?);

    Как сделать так, чтобы эту переменную А можно было взять через getenv(),
    т.е. что еще нужно добавить, чтобы она появилась в переменных окружения интерпретатора, из-под которого запускается моя программа на С.

    Спасибо.
    Сообщение отредактировано: alkor -
      system("export MY_ENV_VARIABLE=MY_VALUE");

      no pravilnee inicializirovat' vse peremennie pri otkritiy novoy sessiy
        А под каким шелом прога то выполняется?
        для bash
        system("MY_VAR=eprst; export MY_VAR");

        для tc
        system("setenv MY_VAR eprst");
          setenv(...)
            Цитата
            В сишной пронрамме я пользуюсь функцией system();

            system('some_command'\nA=$?);

            Как сделать так, чтобы эту переменную А можно было взять через getenv(),
            т.е. что еще нужно добавить, чтобы она появилась в переменных окружения интерпретатора, из-под которого запускается моя программа на С.

            Спасибо.


            Ответ очень прост - никак. Из потомка нет доступа к environment предка. То, что ты запускаешь с помощью system() исполняется шеллом, который будет потомком твой программы. Если ты в потомке взвел какие-то переменные среды, то родитель о них ничего не узнает, так как адресные пространства у процессов не пересекаются.

            Единственное, что ты можешь сделать, это исправить собственную среду окружения твоей проги. Это можно сделать (как правильно отметил makedonskij) с помощью setenv(). Такая переменная среды будет наследоваться всеми новыми потомками твоей програмыы (среда старых потомков не изменится )
              Цитата borunov, 07.10.02, 10:26:24


              Ответ очень прост - никак. Из потомка нет доступа к environment предка. То, что ты запускаешь с помощью system() исполняется шеллом, который будет потомком твой программы. Если ты в потомке взвел какие-то переменные среды, то родитель о них ничего не узнает, так как адресные пространства у процессов не пересекаются.

              Единственное, что ты можешь сделать, это исправить собственную среду окружения твоей проги. Это можно сделать (как правильно отметил makedonskij) с помощью setenv(). Такая переменная среды будет наследоваться всеми новыми потомками твоей програмыы (среда старых потомков не изменится )


              Неправда. Инструкция ". export MY_ENV=MY_VALUE" определяет переменную окружения в процессе init. Соответственно, вся иерархия процессов данной сессии видит установленную переменную окружения
                2 alexsh:
                Неправ как раз ты - допускаешь очень распространенную ошибку. Давай рассмотрим упрощенный пример, эквивалентный поведению init (не циклический и без навороченных конфигов)

                Вот смотри код ниже - он делает следующее:
                   1. запускает отцовский процесс
                   2. отец распечатывает свои переменные среды
                   3. отец запускает ребенка
                   4. отец меняет среду
                   5. отец распечатывает свои переменные среды
                   6. ребенок распечатывает свои переменные среды

                Цитата
                /*for printf(), perror()*/
                #include <stdio.h>
                /*for putenv()*/
                #include <stdlib.h>
                /*for fork(), sleep()*/
                #include <unistd.h>
                /*for wait()*/
                #include <sys/types.h>
                #include <sys/wait.h>

                extern char **environ;
                int child_stat;

                void print_env (header)
                   char *header;
                {
                   int i;

                   printf ("-= \%s =-\n", header);
                   for (i = 0; environ[i] != NULL; i++)
                       printf("\%s\n", environ[i]);
                }
                int main (argc, argv, env)
                   int argc;
                   char **argv;
                   char **env;
                {
                   print_env ("Father, before environ changes");

                   /*Let's born a child*/
                   switch (fork ())
                   {
                       case 0: /*Child*/
                           sleep (2); /*Child's and father's output do not overlap*/
                           print_env("Child, after father's environ changes");
                           break;

                       case -1: /*Error*/
                           perror ("Could not fork()");
                           break;

                       default: /*Father*/
                           putenv ("LAMER=TEST"); /* It changes "environ", but not "env"*/
                           print_env ("Father, after environ changes");
                           wait (&child_stat); /*Wait for child to terminate*/
                           break;
                   }
                   return 0;
                }

                Как нетрудно видеть после исполнения этого кода - первая и третья распечатки среды будут одинаковы, а вот вторая - будет иметь новую переменную LAMER. Это значит, что уже работающий процесс не получает никакого уведомления, если его отец меняет свою среду. Если бы я поместил в коде putenv() до вызова fork(), то ребенок имел бы уже измененную среду, так как он был бы порожден после ее изменения.

                Теперь объясняю, в чем твоя ошибка с init.... init - самый первый процесс в системе. Все остальные процессы стартуют из-под него и после него, образуя многоуровневую иерархию (я здесь не рассматриваю виртуальные треды ядра и т.п. вирт. процессы). Естественно, что они наследуют все его перменные среды. Потом они их, конечно могут удалять и менять в своем контексте.

                Поставь эксперимент - измени в своей системе файл inittab, добавив какую-нибудь переменную. Стрельни по init-у HUP-сигналом, чтоб он перечитал конфиг. И что ты видишь - изменилась в твоем текущем шелле среда? добавилась новая переменная? ну конечно нет, хоть твой шелл и потомок init-а (не сын, но правнук), до него эти изменения не дойдут. Но если init запустит что-то после твоего HUP-а, то новые процессы уже отнаследуют новую переменную среды.

                Кстати, init очень часто растартует процессы, которые описаны в его конфиге и по какой-то причине померли - см. например "respawn" в man-е по init.
                  Не хочу вступать в длинную дисскуссию, просто предлагау выполнить приведенную мною выше инструкцию ". export MY_ENV=MY_VALUE"  и проверить, установлены переменные окружения, или нет. Зарание скажу, что проверял на AIX, COMPAQ Tru64, SUN/SOLARIS.
                  И кстати, обрати внимание, что я ни словом не обмолвился о putenv() function, так как она действует именно так, как ты описал.
                    2 alexsh:

                    Я не первый год в юниксе и уверен, что ты ошибаешься. Но все-таки, я проделал следующие действия ;) :

                    #env
                    <длинный список переменных- skipped>
                    #echo . export MY_VAR=MY_VALUE >> /etc/inittab
                    #init q
                    #env
                    <почти тот же самый длинный список, в нем MY_VAR не фигурирует>
                    #uname -a
                    OSF1 ruaxp1.skipped.skipped.skipped V5.1 1885 alpha

                    Что и требовалось доказать. Проделал я это (как ты видишь) на Compaq True64 V5.1A (Rev.1885). К такому же результату (вернее к его отсутствию) приводит это и на HP-UX 11.0 (uname -a: "HP-UX mguors B.11.00 U 9000/800 101901597 unlimited-user license"). Дома могу проверить с FreeBSD 4.6.2, но думаю смысла в этом нет.

                    Если я проделал не то, что ты от меня хотел - объясни, что мне сделать, чтоб MY_VAR от init-а до шелла дошел по иерархии :).

                    Я же говорю - нет такого способа. У процессов память изолирована друг от дружки, пока явно не попросишь ее разделять (shared memory, etc....) с кем-то еще.
                    0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                    0 пользователей:


                    Рейтинг@Mail.ru
                    [ Script execution time: 0,0246 ]   [ 15 queries used ]   [ Generated: 27.04.24, 21:07 GMT ]