Můžete si přečíst počáteční prostředí procesu z /proc/<pid>/environ
.
Pokud se proces změní jeho prostředí, pak pro čtení prostředí musíte mít tabulku symbolů pro proces a použít ptrace
systémové volání (například pomocí gdb
) pro čtení prostředí z globálního char **__environ
variabilní. Neexistuje žádný jiný způsob, jak získat hodnotu jakékoli proměnné ze spuštěného linuxového procesu.
To je odpověď. Nyní několik poznámek.
Výše uvedené předpokládá, že proces je kompatibilní s POSIX, což znamená, že proces spravuje své prostředí pomocí globální proměnné char **__environ
jak je uvedeno v Ref Spec.
Počáteční prostředí pro proces je předáno procesu ve vyrovnávací paměti s pevnou délkou v zásobníku procesu. (Obvyklý mechanismus, který to dělá, je linux//fs/exec.c:do_execve_common(...)
.) Vzhledem k tomu, že velikost vyrovnávací paměti je vypočítána tak, aby nebyla větší než velikost požadovaná pro počáteční prostředí, nemůžete přidávat nové proměnné bez vymazání existujících proměnných nebo rozbití zásobníku. Jakékoli rozumné schéma umožňující změny v prostředí procesu by tedy využívalo haldu, kde lze alokovat a uvolnit paměť v libovolných velikostech, což je přesně to, co GNU libc
(glibc
) dělá pro vás.
Pokud proces používá glibc
, pak je kompatibilní s POSIX s __environ
deklarován v glibc//posix/environ.c
Glibc inicializuje __environ
s ukazatelem do paměti, že malloc
s z haldy procesu, poté zkopíruje počáteční prostředí ze zásobníku do této oblasti haldy. Pokaždé, když proces používá setenv
funkce, glibc
udělá realloc
upravit velikost oblasti, která __environ
ukazuje na pro přizpůsobení nové hodnotě nebo proměnné. (Zdrojový kód glibc si můžete stáhnout pomocí git clone git://sourceware.org/git/glibc.git glibc
). Abyste skutečně pochopili mechanismus, budete si muset přečíst také Hurd kód v hurd//init/init.c:frob_kernel_process()
(klon git git://git.sv.gnu.org/hurd/hurd.git hurd).
Nyní, pokud je nový proces pouze fork
ed, bez následných exec
přepsáním zásobníku, pak se kouzlo zkopírování argumentů a prostředí provede v linux//kernel/fork.c:do_fork(...)
, kde copy_process
rutinní volání dup_task_struct
který alokuje zásobník nového procesu voláním alloc_thread_info_node
, který se nazývá setup_thread_stack
(linux//include/linux/sched.h
) pro nový proces pomocí alloc_thread_info_node
.
Nakonec POSIX __environ
konvence je uživatelský prostor konvence. Nemá žádnou souvislost s ničím v linuxovém jádře. Program v uživatelském prostoru můžete napsat bez použití glibc
a bez __environ
globální a pak spravujte proměnné prostředí, jak chcete. Nikdo vás za to nezatkne, ale budete si muset napsat své vlastní funkce správy prostředí (setenv
/getenv
) a vaše vlastní obálky pro sys_exec
a je pravděpodobné, že nikdo nebude schopen uhodnout, kam jste změny ve svém prostředí umístili.
/proc/$pid/environ
aktualizuje, pokud proces změní své vlastní prostředí. Ale mnoho programů se neobtěžuje měnit své vlastní prostředí, protože je to trochu zbytečné:prostředí programu není viditelné normálními kanály, pouze pomocí /proc
a ps
a dokonce ani ne každá unixová varianta má tento druh funkce, takže aplikace na ni nespoléhají.
Pokud jde o jádro, prostředí se objevuje pouze jako argument execve
systémové volání, které spustí program. Linux zpřístupňuje oblast v paměti prostřednictvím /proc
a některé programy tuto oblast aktualizují, zatímco jiné ne. Zejména si nemyslím, že žádný shell aktualizuje tuto oblast. Protože oblast má pevnou velikost, nebylo by možné přidávat nové proměnné nebo měnit délku hodnoty.
Aktualizuje se, když proces získá/vymaže své proměnné prostředí. Máte odkaz, který uvádí environ
soubor není aktualizován pro proces v jeho adresáři procesu pod /proc filesystem?
xargs --null --max-args=1 echo < /proc/self/environ
nebo
xargs --null --max-args=1 echo < /proc/<pid>/environ
nebo
ps e -p <pid>
Výše uvedené vypíše proměnné prostředí procesu v ps
výstupní formát, k zobrazení proměnných prostředí jako seznamu je vyžadováno zpracování textu (analýza/filtrování).
Solaris (není dotazován, ale pro referenci zde zveřejním):
/usr/ucb/ps -wwwe <pid>
nebo
pargs -e <pid>
UPRAVIT: /proc/pid/environ není aktualizován! stojím opravený. Ověřovací proces je níže. Nicméně děti, od kterých je proces rozvětvený, zdědí proměnnou prostředí procesu a je viditelná v jejich příslušném souboru /proc/self/environ. (Použijte řetězce)
S v shellu:zde je xargs podřízený proces, a proto zdědí proměnnou prostředí a také se odráží ve svém /proc/self/environ
soubor.
[[email protected] t]$ printenv | grep MASK
[[email protected] t]$ export MASK=NIKHIL
[[email protected] t]$ printenv | grep MASK
MASK=NIKHIL
[[email protected] t]$ xargs --null --max-args=1 echo < /proc/self/environ | grep MASK
MASK=NIKHIL
[[email protected] t]$ unset MASK
[[email protected] t]$ printenv | grep MASK
[[email protected] t]$ xargs --null --max-args=1 echo < /proc/self/environ | grep MASK
[[email protected] t]$
Kontrola z jiné relace, kde terminál/relace není podřízeným procesem shellu, kde je nastavena proměnná prostředí.
Ověření z jiného terminálu/relace na stejném hostiteli:
terminál1: :Všimněte si, že printenv je rozvětvený a je podřízeným procesem bash, a proto čte svůj vlastní soubor environ.
[[email protected] t]$ echo $$
2610
[[email protected] t]$ export SPIDEY=NIKHIL
[[email protected] t]$ printenv | grep SPIDEY
SPIDEY=NIKHIL
[[email protected] t]$
terminál2: na stejném hostiteli – nespouštějte jej ve stejném prostředí, kde byla nastavena výše uvedená proměnná, spusťte terminál samostatně.
[[email protected] ~]$ echo $$
4436
[[email protected] ~]$ xargs --null --max-args=1 echo < /proc/self/environ | grep -i spidey
[[email protected] ~]$ strings -f /proc/2610/environ | grep -i spidey
[[email protected] ~]$ xargs --null --max-args=1 echo < /proc/2610/environ | grep -i spidey
[[email protected] ~]$