Експортувати змінну env, щоб бути доступною для всіх підрозділів, і можливо змінити?


22

Припустимо, я маю

export MY_VAR=0

в ~/.bashrc.

У мене відкритий термінал gnome, і в цьому терміналі я змінюю $MY_VARзначення на 200. Отже, якщо я

echo $MY_VAR

в цьому терміналі, 200показано.

Тепер я відкрив ще одну вкладку в своєму терміналі gnome, і так

echo $MY_VAR

... а замість цього 200я 0.

Що мені робити, щоб зберегти значення 200, коли термінал модифікує змінну середовища, зробивши цю модифікацію (встановлення на 200) доступною для всіх наступних під оболонок тощо? Чи можливо це?

Відповіді:


23

Копія з середовища поширюється на суб-оболонки, так це працює:

$ export MY_VAR=200
$ bash
$ echo $MY_VAR
200

але оскільки це копія, ви не можете отримати це значення до батьківської оболонки - принаймні, не змінюючи оточення.

Це здається, що ви насправді хочете піти на крок далі, а саме - зробити щось, що діє як глобальна змінна, поділяється "обробляючими" оболонками, ініційованими окремо від батьківського, як ваша нова вкладка в терміналі Gnome.

Здебільшого, відповідь "ви не можете, тому що змінні середовища не працюють таким чином". Однак є ще одна відповідь, яка полягає в тому, що ви завжди можете щось зламати. Одним із підходів було б записати значення змінної у файл, як-от ~/.myvar, а потім включити це в ~/.bashrc. Потім кожна нова оболонка розпочнеться зі значення, прочитаного з цього файлу.

Ви можете піти на крок далі - введіть ~/.myvarформат MYVAR=200, а потім встановіть PROMPT_COMMAND=source ~/.myvar, що призведе до того, що значення буде перечитуватися кожного разу, коли ви отримуєте нове підказку. Це все ще не зовсім спільна глобальна змінна, але вона починає діяти так. Він не активується, поки не повернеться підказка, що залежно від того, що ви намагаєтесь зробити, може бути серйозним обмеженням.

І тоді, звичайно, наступне - це автоматично записати зміни в ~/.myvar. Це стає дещо складнішим, і я зупинюсь на цьому, тому що дійсно змінні середовища не повинні були бути механізмом зв'язку між оболонками, а краще просто знайти інший спосіб зробити це.


10
Я можу почути, як під тортурами

Так вибачте Тому я зупинився. :)
mattdm

"що полягає в тому, щоб зробити щось, що діє як глобальна змінна" - Ну, справді, саме це я намагався досягти. ~ / .Myvar не дуже, але він працює. У вас є ще одна пропозиція?
Хтось досі використовує вас MS-DOS

2
Що ж, давайте трохи відступимо. Чому ви хочете глобальну змінну?
mattdm

1
@mattdm: У мене є деякі "бюрократії", яким я повинен підкорятися. Один з них - це купа кодів, які мені потрібно зробити разом із коментарем. Ці коди зараз перебувають у ієрархії папок (домашній / користувач / проекти / код проекту / код1 / код2). Я зробив функцію, яка витягує code1 та code2 для env vars (тому коли мені потрібно займатися, я просто викликаю функцію всередині dir з кодами), і я під час комутації використовую vim і є деякі функції, які прочитайте ці варіанти і введіть коментар автоматично. Я думаю, що використання файлів для цього може бути рішенням.
Хтось досі використовує вас MS-DOS

13

Припустимо, я export MY_VAR=0в ~/.bashrc.

Це ваша помилка саме там. Ви повинні визначити змінні середовища в ~/.profile, яке читається при вході в систему. ~/.bashrcЧитається кожного разу при запуску оболонки; коли ви запускаєте внутрішню оболонку, вона змінюється MY_VAR. Якщо ви цього не зробили, ваша змінна середовище поширюватиметься вниз.

Для отримання додаткової інформації про ~/.bashrcvs ~/.profileдив. Мої попередні публікації на цю тему .

Зауважте, що поширення вгору (отримання зміненого значення з підшару автоматично відображається в батьківській оболонці) неможливо, повна зупинка.



3

Не використовуйте змінні середовища взагалі. Використовуйте файли.

Щоб процеси не наступали один на одного під час оновлення / читання файлу, використовуйте фіксатори та невеликі сценарії оновлення переднього плану, метою яких є лише оновлення файлу на 1 долар, якщо він не заблокований. Файли блокування реалізуються, в основному, перевіряючи, чи існує певний файл (/var/run/yourscript.lck), і якщо він є, зачекайте, поки файл зникне на деякий час, і не вдасться, якщо він не відбудеться. Також ви повинні видалити файл блокування, коли закінчите оновлення файлу.

Будьте готові вирішити ситуацію, коли сценарій не може оновити файл, оскільки файл зайнятий.


8
Трюк: використовуйте каталоги замість файлів для блокування, оскільки це mkdirпрацює як атомний тест-і-створення.
mattdm

1
Якщо ви хочете поговорити про блокування, то ви можете також скористатисяflock(2)
Ehtesh Choudhury

@mattdm Я виявив, що символьне посилання ln -s dummy lockfile(навіть якщо воно порушено) може також працювати, оскільки воно не вдасться, якщо символьне посилання вже існує. Цікаво, як перевірити, чи справді це на 100% безпечно.
Сила Водолія

1

Коли я просто переглянув це питання, я намагався вирішити проблему оновлення стану (тобто змінних оболонок) із позадіагностичних пакетів. Так, щоб можна було призначити змінні, скажімо, всередині конвеєра - і призначення було б чітко видно для батьків.

Звичайно, це неможливо простим способом, оскільки окремі частини трубопроводу виконуються в підрозділах, які видаються forkз батьківської оболонки і, отже, мають пам'ять, що є переглядом копіювання під час запису в пам'ять батьків. Однак я припускав, що тонке і прозоре рішення може бути можливим на основі IPC-коду, що використовується " спільною пам'яттю " .

І я навіть знайшов реалізацію саме цієї конструкції ... але це в Perl.

Додавши цю відповідь все одно як можливе рішення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.