Есть ли способ изменить переменные среды другого процесса в Unix?

Есть ли в Unix способ, которым один процесс может изменять переменные среды другого (при условии, что все они запускаются одним и тем же пользователем)? Лучше всего было бы общее решение, но если нет, как насчет конкретного случая, когда один является потомком другого?

Обновлено: как насчет через GDB?

Мне это кажется более чем уродливым. Какую проблему вы хотите решить?

Jens 02.06.2012 12:30

Пример: я хотел бы определить переменную среды, чтобы каждое новое приложение, запускаемое пользовательским интерфейсом, получало ее. Я не знаю ни одного метода, кроме определения переменных в одном из сценариев запуска и RE-LOGIN. Однако я бы хотел не повторно входить в систему, а просто определить переменные в текущем сеансе, чтобы новые приложения получали их - без выхода из пользовательского интерфейса.

AlikElzin-kilaka 22.07.2012 19:18
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
106
2
40 334
11
Перейти к ответу Данный вопрос помечен как решенный

Ответы 11

Если ваш unix поддерживает файловую систему / proc, то ПРОЧИТАТЬ env тривиально - таким образом вы можете читать среду, командную строку и многие другие атрибуты любого процесса, которым вы владеете. Изменить это ... Ну, я могу придумать способ, но это ПЛОХАЯ идея.

Более общий случай ... Я не знаю, но сомневаюсь, что есть переносимый ответ.

(Отредактировано: мой первоначальный ответ предполагал, что OP хочет ПРОЧИТАТЬ env, а не изменять его)

Ой, отредактировал свой ответ - я предполагал, что он хочет прочитать env, а не изменять его.

Mike G. 15.10.2008 19:12

Не оставляй меня висеть. Какая у тебя плохая идея?

raldi 15.10.2008 19:23

Я считаю, что в Linux вы МОЖЕТЕ открыть / proc / <pid> / mem для чтения и записи для другого процесса, которым вы владеете ... Я не уверен. Пытаться и на самом деле возиться с окружающей средой ОПРЕДЕЛЕННО будет плохой идеей. Так что я не предлагаю вам попробовать ...

Mike G. 16.10.2008 04:22

Цитата Джерри Пика:

You can't teach an old dog new tricks.

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

Подробнее см. http://www.unix.com.ua/orelly/unix/upt/ch06_02.htm.

Просто комментарий к ответу об использовании / proc. Под linux / proc поддерживается, но это не работает, вы не могу изменяете файл /proc/${pid}/environ, даже если вы root: он доступен только для чтения абсолютно.

Остается вопрос: где на самом деле хранятся значения env var? Это делает ядро? Или оболочка хранит значения, а / proc / <pid> / Environment получает их оттуда?

oliver 16.10.2008 20:46

Это деталь реализации, и это может быть (отдельный) хороший вопрос. Я думаю, что каждая UNIX использует свой собственный способ хранения, но все они разделяют поведение, описанное выше, что является частью спецификаций.

Davide 17.10.2008 00:09

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

Или попросите свой процесс обновить файл конфигурации для нового процесса, а затем либо:

  • выполнить kill -HUP для нового процесса, чтобы перечитать обновленный файл конфигурации, или
  • пусть процесс время от времени проверяет конфигурационный файл на наличие обновлений. Если изменения обнаружены, то перечитайте файл конфигурации.

Я мог бы придумать довольно надуманный способ сделать это, и он не будет работать для произвольных процессов.

Предположим, вы пишете свою собственную общую библиотеку, которая реализует char * getenv. Затем вы настраиваете окружение LD_PRELOAD или LD_LIBRARY_PATH. vars, чтобы оба процесса запускались с предварительно загруженной общей библиотекой.

Таким образом, у вас будет практически полный контроль над кодом функции getenv. Тогда вы сможете проделывать всевозможные неприятные трюки. Ваш 'getenv' может обращаться к внешнему файлу конфигурации или сегменту SHM для получения альтернативных значений переменных env. Или вы можете выполнить поиск / замену регулярного выражения для запрошенных значений. Или же ...

Я не могу придумать простой способ сделать это для произвольных запущенных процессов (даже если вы - root), кроме как переписать динамический компоновщик (ld-linux.so).

Это должно быть выполнимо. У вас может быть небольшая база данных gdbm для пар var = value. У меня есть что-то подобное для malloc на stromberg.dnsalias.org/~strombrg/malloc-wrapper

dstromberg 23.04.2019 07:18

Я думаю, что этот метод требует предусмотрительности. Вы также должны быть осторожны, чтобы случайно не применить его ко многим процессам.

dstromberg 23.04.2019 07:25

По сути, нет. Если у вас были достаточные привилегии (root или около того) и вы пробовали / dev / kmem (память ядра), и вы внесли изменения в среду процесса, и если процесс действительно впоследствии повторно ссылался на переменную среды (то есть процесс еще не сделал копию env var и не использовал только эту копию), тогда, возможно, если вам повезло и умен, и ветер дул в правильном направлении, и фаза луны была правильной, возможно, вы можете чего-то добиться.

@kilaka: Ключевое слово - второе - Нет. Остальная часть ответа говорит о том, что если у вас есть привилегии root или вы используете отладчик, то, возможно, вы сможете это сделать, но для всех практических целей ответ - Нет.

Jonathan Leffler 22.07.2012 19:31

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

Jonathan Leffler 25.07.2012 21:21
Ответ принят как подходящий

Через GDB:

(gdb) attach process_id

(gdb) call putenv ("env_var_name=env_var_value")

(gdb) detach

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

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

grieve 05.11.2008 23:43

"Кажется, можно было бы написать программу, которая только это делает". Действительно ... это так.

L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ 24.02.2010 02:22

Он работает даже в Windows с использованием cygwin для процессов, которые не скомпилированы с использованием cygwin!

Juan Carlos Muñoz 05.10.2012 22:39

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

An̲̳̳drew 24.06.2013 19:12

Удивительно, но это действительно работает. Я смог добавить переменную окружения к запущенному сеансу X / MATE, используя эту технику для mate-session и mate-panel. Недавно запущенные терминалы унаследовали переменную, как и обычно.

Animism 09.02.2014 09:37

ptrace: Operation not permitted

gerrit 22.03.2014 19:30

Кстати. этот сценарий оболочки позволяетsudo export_pid FOO=bar 11234 с использованием метода GDB. Пс. gdb требует, чтобы вы запускались как root.

coderofsalvation 24.06.2015 13:53

Я применил этот ответ, чтобы изменить часовой пояс в работающем экземпляре IRSSI, вызвав putenv («TZ = / path / to / timezone»).

Patrick Conheady 23.09.2016 08:25

Я получаю эту ошибку: No symbol "setenv" in current context.

vaibhavatul47 14.12.2017 08:34

Обновление: sourceware.org/gdb/onlinedocs/gdb.html#Environment это помогло.

vaibhavatul47 14.12.2017 09:53

В некоторых системах gdb может выдать следующую ошибку: 'putenv' has unknown return type; cast the call to its declared return type; в этих случаях вы должны изменить вызов putenv на этот: call (int) putenv ("env_var_name=env_var_value")

Emir Uner 20.02.2019 12:33

Что делать, если в процессе вы увеличиваете пространство, выделенное для env vars? Это перезаписывает что-то еще? То есть, если изначально VAR = valuex и вы используете gdbm для setenv / putenv VAR = valuexy, вы переполняете буфер?

dstromberg 23.04.2019 07:23

Вы, вероятно, можете сделать это технически (см. Другие ответы), но это может вам не помочь.

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

Если вы разместили это как конкретную проблему, вам, вероятно, следует использовать другой подход. Если бы это было просто из любопытства: Хороший вопрос :-).

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

Hjulle 10.12.2018 14:40

Не прямой ответ, но ... Только на днях у Раймонда Чена было объяснение этому [на основе Windows].: -

... Although there are certainly unsupported ways of doing it or ways that work with the assistance of a debugger, there’s nothing that is supported for programmatic access to another process’s command line, at least nothing provided by the kernel. ...

That there isn’t is a consequence of the principle of not keeping track of information which you don’t need. The kernel has no need to obtain the command line of another process. It takes the command line passed to the CreateProcess function and copies it into the address space of the process being launched, in a location where the GetCommandLine function can retrieve it. Once the process can access its own command line, the kernel’s responsibilities are done.

Since the command line is copied into the process’s address space, the process might even write to the memory that holds the command line and modify it. If that happens, then the original command line is lost forever; the only known copy got overwritten.

Другими словами, любые такие средства ядра будут

  • сложно реализовать
  • потенциально проблема безопасности

Однако наиболее вероятная причина просто в том, что существует ограниченное количество вариантов использования такого средства.

UNIX полон межпроцессного взаимодействия. Проверьте, есть ли у вашего целевого экземпляра. Dbus становится стандартом в «настольных» IPC.

Я меняю переменные окружения внутри оконного менеджера Awesome, используя потрясающий клиент с Dbus «отправителем» кода lua.

Кажется, что путенв сейчас не работает, а setenv работает. Я тестировал принятый ответ, безуспешно пытаясь установить переменную в текущей оболочке

$] sudo gdb -p $$
(gdb) call putenv("TEST=1234")
$1 = 0
(gdb) call (char*) getenv("TEST")
$2 = 0x0
(gdb) detach
(gdb) quit
$] echo "TEST=$TEST"
TEST=

и вариант, как это работает:

$] sudo gdb -p $$
(gdb) call (int) setenv("TEST", "1234", 1)
$1 = 0
(gdb) call (char*) getenv("TEST")
$2 = 0x55f19ff5edc0 "1234"
(gdb) detach
(gdb) quit
$] echo "TEST=$TEST"
TEST=1234

Другие вопросы по теме