Linux /proc/<pid>/environне обновляется (насколько я понимаю, файл содержит исходную среду процесса).
Как я могу прочитать текущую среду процесса ?
Linux /proc/<pid>/environне обновляется (насколько я понимаю, файл содержит исходную среду процесса).
Как я могу прочитать текущую среду процесса ?
Ответы:
/proc/$pid/environобновляется, если процесс изменяет свою собственную среду. Но многие программы не беспокоятся об изменении собственной среды, потому что это немного бессмысленно: среда программы не видна через обычные каналы, только через /procи ps, и даже не в каждом варианте Unix есть такая функция, поэтому приложения не полагаются в теме.
Что касается ядра, окружение появляется только в качестве аргумента execveсистемного вызова, запускающего программу. Linux раскрывает область в памяти /proc, и некоторые программы обновляют эту область, а другие - нет. В частности, я не думаю, что какая-либо оболочка обновляет эту область. Поскольку область имеет фиксированный размер, было бы невозможно добавить новые переменные или изменить длину значения.
PATH=fooв оболочке, не означает, что оболочка будет изменена *envp. В некоторых оболочках обновляется только внутренняя структура данных, и обновляется код выполнения внешней программы *envp. Посмотрите assign_in_envв variables.cв источнике Баш, например.
forkто libc выполняет sys_forkвызов, используя выделенную кучу среду для дочернего процесса.
argvболее распространены, но оба существуют).
Вы можете прочитать исходную среду процесса из /proc/<pid>/environ.
Если процесс изменяет свою среду, то для чтения среды необходимо иметь таблицу символов для процесса и использовать ptraceсистемный вызов (например, с помощью gdb) для чтения среды из глобальной char **__environпеременной. Нет другого способа получить значение любой переменной из запущенного процесса Linux.
Это ответ. Теперь о некоторых заметках.
Выше предполагается, что процесс совместим с POSIX, что означает, что процесс управляет своей средой, используя глобальную переменную, char **__environкак указано в Ссылочной спецификации .
Начальная среда для процесса передается процессу в буфере фиксированной длины в стеке процесса. (Обычный механизм, который делает это linux//fs/exec.c:do_execve_common(...).) Поскольку размер буфера рассчитывается не больше, чем размер, необходимый для начальной среды, вы не можете добавить новые переменные, не удалив существующие переменные или не разрушив стек. Таким образом, любая разумная схема, позволяющая вносить изменения в среду процесса, будет использовать кучу, в которой можно выделять и освобождать память произвольных размеров, что в точности делает для вас GNU libc( glibc).
Если процесс использует glibc, то он является POSIX-совместимым, __environпоскольку объявление в glibc//posix/environ.cGlibc инициализируется __environуказателем на память mallocиз кучи процесса, а затем копирует исходную среду из стека в эту область кучи. Каждый раз, когда процесс использует setenvфункцию, glibcвыполняет reallocнастройку размера области, на которую __environуказывает новое значение или переменная. (Вы можете скачать исходный код glibc с помощью git clone git://sourceware.org/git/glibc.git glibc). Чтобы по-настоящему понять механизм, вам также нужно прочитать код Hurd в hurd//init/init.c:frob_kernel_process()(git clone git: //git.sv.gnu.org/hurd/hurd.git hurd).
Теперь, если новый процесс редактируется только forkбез последующей execперезаписи стека, тогда происходит волшебство копирования аргумента и среды linux//kernel/fork.c:do_fork(...), когда copy_processподпрограммы вызывают dup_task_structвыделение стека нового процесса путем вызова alloc_thread_info_node, который вызывает setup_thread_stack( linux//include/linux/sched.h) для нового процесса, использующего alloc_thread_info_node.
Наконец, __environсоглашение POSIX является соглашением пространства пользователя . Он не имеет ничего общего с ядром Linux. Вы можете написать программу пользовательского пространства без использования glibcи без __environглобальных параметров, а затем управлять переменными среды по своему усмотрению. Никто не арестует вас за это, но вам придется написать свои собственные функции управления средой ( setenv/ getenv) и свои собственные оболочки, sys_execи, вероятно, никто не сможет угадать, куда вы вносите изменения в вашу среду.
/proc/[pid]/имеют странную кодировку (кто-то другой может знать, что и почему). Для меня просто cat environвывести переменные окружения в действительно трудном для чтения формате. cat environ | stringsрешил это для меня.
Он обновляется по мере того, как и когда процесс получает / удаляет свои переменные окружения. У вас есть ссылка, в которой говорится, что environфайл не обновляется для процесса в его каталоге процессов в / proc файловой системы?
xargs --null --max-args=1 echo < /proc/self/environ
или
xargs --null --max-args=1 echo < /proc/<pid>/environ
или
ps e -p <pid>
Выше будет печатать переменные среды процесса в psвыходном формате, обработка текста (анализ / фильтрация) требуется, чтобы увидеть переменные среды в виде списка.
Солярис (не спрашивал, но для справки выложу здесь):
/usr/ucb/ps -wwwe <pid>
или
pargs -e <pid>
РЕДАКТИРОВАТЬ: / proc / pid / environment не обновляется! Я стою исправлено. Процесс проверки ниже. Однако потомки, от которых процесс является fork, наследуют переменную среды процесса, и это видно в их соответствующем файле / proc / self / environment. (Используйте строки)
В оболочке: здесь xargs является дочерним процессом и, следовательно, наследует переменную окружения, а также отражается в его /proc/self/environфайле.
[centos@centos t]$ printenv | grep MASK
[centos@centos t]$ export MASK=NIKHIL
[centos@centos t]$ printenv | grep MASK
MASK=NIKHIL
[centos@centos t]$ xargs --null --max-args=1 echo < /proc/self/environ | grep MASK
MASK=NIKHIL
[centos@centos t]$ unset MASK
[centos@centos t]$ printenv | grep MASK
[centos@centos t]$ xargs --null --max-args=1 echo < /proc/self/environ | grep MASK
[centos@centos t]$
Проверка его из другого сеанса, где терминал / сеанс не является дочерним процессом оболочки, в которой установлена переменная среды.
Проверка из другого терминала / сеанса на том же хосте:
Terminal1:: Обратите внимание, что printenv является fork'd и является дочерним процессом bash, и, следовательно, он читает свой собственный файл окружения.
[centos@centos t]$ echo $$
2610
[centos@centos t]$ export SPIDEY=NIKHIL
[centos@centos t]$ printenv | grep SPIDEY
SPIDEY=NIKHIL
[centos@centos t]$
терминал2: на том же хосте - не запускайте его в той же оболочке, где была установлена вышеуказанная переменная, запускайте терминал отдельно.
[centos@centos ~]$ echo $$
4436
[centos@centos ~]$ xargs --null --max-args=1 echo < /proc/self/environ | grep -i spidey
[centos@centos ~]$ strings -f /proc/2610/environ | grep -i spidey
[centos@centos ~]$ xargs --null --max-args=1 echo < /proc/2610/environ | grep -i spidey
[centos@centos ~]$
export foo=barв одном сеансе bash (pid xxxx), затем делаю cat /proc/xxxx/environ | tr \\0 \\nв другом сеансе bash, и я не вижу foo.
gdb к pid, но там до сих пор нет ссылок. Блок переменных среды в памяти перераспределяется всякий раз, когда происходит изменение, и не отражается в файле окружения своего собственного процесса в файловой системе proc, но, тем не менее, позволяет наследоваться дочерним процессом. Это означает, что это может быть легче узнать внутренние детали, когда происходит разветвление, как дочерний процесс получает переменные среды, скопированные как есть.
Что ж, следующее не связано с реальными намерениями автора, но если вы действительно хотите «ПРОЧИТАТЬ» /proc/<pid>/environ, вы можете попробовать
strings /proc/<pid>/environ
что лучше, чем catэто.
strings. Будь проще.
xargs --null.
tr '\0' '\n' < /proc/$$/environ | ...