Linux /proc/<pid>/environnie aktualizuje się (jak rozumiem, plik zawiera początkowe środowisko procesu).
Jak mogę odczytać aktualne środowisko procesu ?
Linux /proc/<pid>/environnie aktualizuje się (jak rozumiem, plik zawiera początkowe środowisko procesu).
Jak mogę odczytać aktualne środowisko procesu ?
Odpowiedzi:
/proc/$pid/environaktualizuje się, jeśli proces zmieni własne środowisko. Ale wiele programów nie zawraca sobie głowy zmianą własnego środowiska, ponieważ jest to trochę bezcelowe: środowisko programu nie jest widoczne przez normalne kanały, tylko przez /proci ps, i nawet nie każdy wariant unixa ma taką funkcję, więc aplikacje nie polegają na tym.
Jeśli chodzi o jądro, środowisko pojawia się tylko jako argument execvewywołania systemowego uruchamiającego program. Linux udostępnia obszar pamięci /proc, a niektóre programy aktualizują ten obszar, a inne nie. W szczególności nie sądzę, aby jakakolwiek powłoka aktualizowała ten obszar. Ponieważ obszar ma stały rozmiar, dodanie nowych zmiennych lub zmiana długości wartości byłaby niemożliwa.
PATH=foow powłoce, nie oznacza, że powłoka się zmieni *envp. W niektórych powłokach aktualizuje to tylko wewnętrzną strukturę danych i aktualizuje się zewnętrzny kod wykonania programu *envp. Spójrz na przykład assign_in_envw variables.cźródle bash.
forkto libc wykonuje sys_forkpołączenie, używając środowiska przydzielonego do sterty dla procesu potomnego.
argvsą częstsze, ale oba istnieją).
Możesz odczytać początkowe środowisko procesu z /proc/<pid>/environ.
Jeśli proces zmienia swoje środowisko, to aby odczytać środowisko, musisz mieć tabelę symboli dla procesu i użyć ptracewywołania systemowego (na przykład za pomocą gdb), aby odczytać środowisko ze char **__environzmiennej globalnej . Nie ma innego sposobu uzyskania wartości dowolnej zmiennej z uruchomionego procesu Linux.
To jest odpowiedź. Teraz kilka notatek.
Powyższe zakłada, że proces jest zgodny z POSIX, co oznacza, że proces zarządza swoim środowiskiem przy użyciu zmiennej globalnej char **__environokreślonej w Spec Spec .
Początkowe środowisko dla procesu jest przekazywane do procesu w buforze o stałej długości na stosie procesu. (Zwykłym mechanizmem, który to robi linux//fs/exec.c:do_execve_common(...).) Ponieważ rozmiar bufora jest obliczany jako nie większy niż rozmiar wymagany dla środowiska początkowego, nie można dodawać nowych zmiennych bez usuwania istniejących zmiennych lub niszczenia stosu. Tak więc każdy rozsądny schemat pozwalający na zmiany w środowisku procesu wykorzystywałby stertę, w której pamięć o dowolnych rozmiarach może być przydzielana i zwalniana, co dokładnie robi dla ciebie GNU libc( glibc).
Jeśli proces używa glibc, to jest zgodny z POSIX, a __environdeklaracja w glibc//posix/environ.cGlibc inicjuje __environwskaźnikiem do pamięci, że mallocpochodzi ze sterty procesu, a następnie kopiuje środowisko początkowe ze stosu do tego obszaru sterty. Za każdym razem proces wykorzystuje setenvfunkcję, glibcwymaga się realloc, aby dostosować rozmiar obszaru, który __environwskazuje, aby pomieścić nową wartość lub zmienną. (Możesz pobrać kod źródłowy glibc za pomocą git clone git://sourceware.org/git/glibc.git glibc). Aby naprawdę zrozumieć mechanizm, musisz także przeczytać kod Hurd w hurd//init/init.c:frob_kernel_process()(git clone git: //git.sv.gnu.org/hurd/hurd.git hurd).
Teraz, jeśli nowy proces jest tylko forkedytowany, bez późniejszego execnadpisywania stosu, to magia kopiowania argumentów i środowiska jest wykonywana linux//kernel/fork.c:do_fork(...), gdzie copy_processrutynowe wywołania, dup_task_structktóre przydzielają stos nowego procesu przez wywołanie alloc_thread_info_node, które wywołuje setup_thread_stack( linux//include/linux/sched.h) dla nowego procesu za pomocą alloc_thread_info_node.
Wreszcie __environkonwencja POSIX to konwencja przestrzeni użytkownika . Nie ma połączenia z niczym w jądrze Linuksa. Możesz napisać program przestrzeni użytkownika bez użycia globalnego i glibcbez niego, __environa następnie zarządzać zmiennymi środowiskowymi w dowolny sposób. Nikt cię nie aresztuje za to, ale będziesz musiał napisać własne funkcje zarządzania środowiskiem ( setenv/ getenv) i własne opakowania sys_execi jest prawdopodobne, że nikt nie będzie w stanie zgadnąć, gdzie wprowadzasz zmiany w swoim środowisku.
/proc/[pid]/wydaje się mieć dziwne kodowanie (ktoś inny może wiedzieć, co i dlaczego). Dla mnie po prostu cat environwydrukowałbym zmienne środowiskowe w naprawdę trudnym do odczytania formacie. cat environ | stringsrozwiązałem to dla mnie.
Jest aktualizowany w miarę, jak proces nabywa / usuwa swoje zmienne środowiskowe. Czy masz odniesienie, które stwierdza, że environplik nie jest aktualizowany dla procesu w katalogu procesu w systemie plików / proc?
xargs --null --max-args=1 echo < /proc/self/environ
lub
xargs --null --max-args=1 echo < /proc/<pid>/environ
lub
ps e -p <pid>
Powyżej wydrukuje zmienne środowiskowe procesu w psformacie wyjściowym, przetwarzanie tekstu (parsowanie / filtrowanie) jest wymagane, aby zobaczyć zmienne środowiskowe jako listę.
Solaris (nie pytany, ale w celach informacyjnych opublikuję tutaj):
/usr/ucb/ps -wwwe <pid>
lub
pargs -e <pid>
EDYCJA: / proc / pid / Environment nie jest aktualizowany! Poprawiono mnie. Proces weryfikacji jest poniżej. Jednak elementy potomne, z których rozwidla się proces, dziedziczą zmienną środowiskową procesu i jest ona widoczna w odpowiednim pliku / proc / self / environment. (Użyj ciągów)
With in the shell: tutaj xargs jest procesem potomnym i dlatego dziedziczy zmienną środowiskową, a także odzwierciedla w swoim /proc/self/environpliku.
[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]$
Sprawdzanie go z innej sesji, w której terminal / sesja nie jest procesem potomnym powłoki, w której ustawiona jest zmienna środowiskowa.
Weryfikacja z innego terminala / sesji na tym samym hoście:
terminal1: Zauważ, że printenv jest rozwidlony i jest potomnym procesem bash, a zatem czyta własny plik środowiska.
[centos@centos t]$ echo $$
2610
[centos@centos t]$ export SPIDEY=NIKHIL
[centos@centos t]$ printenv | grep SPIDEY
SPIDEY=NIKHIL
[centos@centos t]$
terminal2: na tym samym hoście - nie uruchamiaj go w tej samej powłoce, w której ustawiono powyższą zmienną, uruchom terminal osobno.
[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=barw sesji jednego basha (pid xxxx), potem robię cat /proc/xxxx/environ | tr \\0 \\nw sesji innego basha i nie widzę foo.
gdb do pid, ale wciąż nie ma tam odniesienia. Blok zmiennych środowiskowych w pamięci zostaje ponownie przydzielony za każdym razem, gdy zachodzi zmiana i nie odzwierciedla pliku środowiska własnego procesu w systemie plików proc, ale pozwala na dziedziczenie przez proces potomny. Oznacza to, że łatwiej będzie poznać wewnętrzne szczegóły, kiedy nastąpi rozwidlenie, w jaki sposób proces potomny pobiera zmienne środowiskowe w takiej postaci, w jakiej są.
Cóż, poniższe informacje nie są powiązane z prawdziwymi intencjami autora, ale jeśli naprawdę chcesz „CZYTAĆ” /proc/<pid>/environ, możesz spróbować
strings /proc/<pid>/environ
co jest lepsze niż catto.
strings. Nie komplikuj.
xargs --null.
tr '\0' '\n' < /proc/$$/environ | ...