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
як зазначено в Ref Spec .
Початкове середовище для процесу передається процесу в буфері фіксованої довжини на стеку процесу. (Звичайний механізм, який це робить linux//fs/exec.c:do_execve_common(...)
.) Оскільки обчислювальний розмір буфера не перевищує розмір, необхідний для початкового середовища, ви не можете додавати нові змінні, не видаляючи існуючі змінні або розбиваючи стек. Отже, будь-яка розумна схема дозволу змін у середовищі процесу використовує купу, де пам'ять у довільних розмірах може бути розподілена та звільнена, що саме GNU libc
( glibc
) робить для вас.
Якщо процес використовує glibc
, то він сумісний з POSIX, __environ
і декларується в glibc//posix/environ.c
Glibc ініціалізується __environ
вказівником на пам'ять, що він знаходиться malloc
з кучі процесу, а потім копіює початкове середовище зі стека в цю область купи. Кожен раз, коли процес використовує setenv
функцію, glibc
робить a, 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
вихідному форматі, необхідна обробка тексту (розбір / фільтрація), щоб побачити змінні середовища як список.
Solaris (не запитують, але для довідки я опублікую тут):
/usr/ucb/ps -wwwe <pid>
або
pargs -e <pid>
EDIT: / proc / pid / Environment не оновлюється! Я стою виправлений. Процес перевірки наведено нижче. Однак діти, від яких процес виходить, успадковують змінну середовища процесу, і це видно у відповідному файлі / proc / self / оточення. (Використовуйте рядки)
З оболонкою: тут 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]$
terminal2: на тому ж хості - не запускайте його в тій же оболонці, де була встановлена вищезгадана змінна, запустіть термінал окремо.
[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 | ...