Linux'lar /proc/<pid>/environ
güncellenmez (anladığım kadarıyla dosya işlemin başlangıç ortamını içerir).
Bir işlemin mevcut ortamını nasıl okuyabilirim ?
Linux'lar /proc/<pid>/environ
güncellenmez (anladığım kadarıyla dosya işlemin başlangıç ortamını içerir).
Bir işlemin mevcut ortamını nasıl okuyabilirim ?
Yanıtlar:
/proc/$pid/environ
İşlem kendi ortamını değiştirirse güncelleme yapar. Bir programın ortamı sadece aracılığıyla normal kanallardan görünmüyorsa: Bu biraz anlamsız çünkü Ama çok program kendi ortamını değiştirerek rahatsız etmeyin /proc
ve ps
hatta değil her unix varyant özelliği bu tür sahiptir uygulamalar güvenmeyin böylece, üstünde.
Çekirdek söz konusu olduğunda, çevre yalnızca execve
programı başlatan sistem çağrısının argümanı olarak görünür . Linux hafızada bir alanı açığa çıkarır /proc
ve bazı programlar bu alanı güncellerken diğerleri bunu yapmaz. Özellikle, hiçbir kabuğun bu alanı güncellediğini sanmıyorum. Alan sabit bir büyüklüğe sahip olduğundan, yeni değişkenler eklemek veya bir değerin uzunluğunu değiştirmek mümkün olmaz.
PATH=foo
bir kabuğa yazmanız , kabuğun değişeceği anlamına gelmez *envp
. Bazı kabuklarda, bu yalnızca bir iç veri yapısını güncelledi ve güncellenen harici program yürütme kodudur *envp
. Bak assign_in_env
içinde variables.c
örneğin bash kaynağında.
fork
yapar sys_fork
.
argv
daha yaygın ancak ikisi de var).
Bir işlemin başlangıç ortamını adresinden okuyabilirsiniz /proc/<pid>/environ
.
Bir işlem ortamını değiştirirse , ortamı okumak için, işlem için sembol tablosuna sahip olmanız ve ortamı genel değişkenden okumak ptrace
için sistem çağrısını kullanmanız gerekir (örneğin, kullanarak gdb
) char **__environ
. Çalışan bir Linux işleminden herhangi bir değişkenin değerini almanın başka bir yolu yoktur.
Cevap bu. Şimdi bazı notlar için.
Yukarıdakiler, işlemin POSIX uyumlu olduğunu, yani işlemin kendi ortamını Ref Spesifikasyonundachar **__environ
belirtildiği şekilde global bir değişken kullanarak yönettiğini varsayar .
Bir işlem için başlangıç ortamı, işlemin yığında sabit uzunlukta bir arabellekte işleme geçirilir. (Bunu yapan olağan mekanizmadır linux//fs/exec.c:do_execve_common(...)
.) Tamponun boyutu, ilk ortam için gereken boyuttan daha fazla olmadığı için hesaplandığından, mevcut değişkenleri silmeden veya yığını bölmeden yeni değişkenler ekleyemezsiniz. Bu nedenle, bir işlem ortamındaki değişikliklere izin vermek için makul olan herhangi bir şema öbek kullanır, isteğe bağlı boyutlardaki hafızanın tahsis edilip serbest bırakılabildiği yığın, GNU libc
( glibc
) tam olarak sizin için ne yapar.
İşlem kullanırsa glibc
, POSIX uyumludur, Glibc'de __environ
bildirilmek suretiyle işlemin glibc//posix/environ.c
öbeğinden __environ
hafızasına bir işaretçi ile başlar malloc
, ardından ilk ortamı yığından bu yığın alanına kopyalar. İşlem setenv
işlevi her kullandığında, glibc
a değerini, yeni değeri veya değişkeni barındırmak için işaret realloc
eden alanın boyutunu ayarlamak için yapar __environ
. (Glibc kaynak kodunu şununla indirebilirsiniz git clone git://sourceware.org/git/glibc.git glibc
). Mekanizmayı gerçekten anlamak için, ayrıca içindeki Hurd kodunu da okumak zorundasınız hurd//init/init.c:frob_kernel_process()
(git clone git: //git.sv.gnu.org/hurd/hurd.git hurd).
Şimdi eğer yeni süreç sadece fork
ed ise, exec
yığının üzerine yazılmadan önce, argüman ve çevre kopyalama sihirbazı içinde yapılır linux//kernel/fork.c:do_fork(...)
, burada copy_process
rutinin dup_task_struct
yeni işlem yığınını çağırarak tahsis ettiği alloc_thread_info_node
, hangi işlemi kullanarak yeni işlemi çağırır setup_thread_stack
( linux//include/linux/sched.h
) kullanır alloc_thread_info_node
.
Son olarak, POSIX __environ
sözleşmesi bir kullanıcı alanı sözleşmesidir. Linux çekirdeğindeki hiçbir şeyle bağlantısı yoktur. Global kullanmadan glibc
ve kullanmadan bir kullanıcı alanı programı yazabilir __environ
ve ardından istediğiniz ortam değişkenlerini yönetebilirsiniz. Bunu yaptığınız için hiç kimse sizi tutuklamayacak, ancak kendi çevre yönetimi işlevlerinizi ( setenv
/ getenv
) ve kendi paketleyicilerini yazmak zorunda kalacaksınız sys_exec
ve hiç kimsenin ortamınızdaki değişiklikleri nereye koyacağınızı tahmin edemeyeceği muhtemel.
/proc/[pid]/
çoğunun garip bir şifrelemesi var gibi görünüyor (başkası ne ve neden olduğunu biliyor olabilir). Benim cat environ
için çevre değişkenlerini okunması zor bir formatta basardım. cat environ | strings
Bunu benim için çözdü.
İşlem ortam değişkenlerini kazandığında / silerken ve olarak güncellenir. environ
/ Proc dosya sistemi altındaki işlem dizininde dosyanın işlem için güncellenmediğini belirten bir referansınız var mı?
xargs --null --max-args=1 echo < /proc/self/environ
veya
xargs --null --max-args=1 echo < /proc/<pid>/environ
veya
ps e -p <pid>
Yukarıdakiler, işlemin ortam değişkenlerini ps
çıktı biçiminde basacaktır, ortam değişkenlerini bir liste olarak görmek için metin işleme (ayrıştırma / filtreleme) gereklidir.
Solaris (istenmedi, ancak referans olarak buraya göndereceğim):
/usr/ucb/ps -wwwe <pid>
veya
pargs -e <pid>
EDIT: / proc / pid / environment güncellenmiyor! Düzeltilmiş duruyorum. Doğrulama işlemi aşağıdadır. Bununla birlikte, işlemin çatallandığı çocuklar, işlem ortamı değişkenini devralır ve ilgili / proc / self / environment dosyasında görülebilir. (Dizeleri kullanın)
Kabuğundaki ile: Burada xargs bir alt işlemdir ve bu nedenle ortam değişkenini miras alır ve ayrıca /proc/self/environ
dosyasına da yansıtır .
[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]$
Terminal / oturumun ortam değişkeninin ayarlandığı kabuğun alt işlemi olmadığı diğer oturumdan kontrol etmek.
Aynı ana bilgisayardaki başka bir terminalden / oturumdan doğrulama:
terminal1:: printenv'nin çatal olduğunu ve bash'ın alt işlemi olduğunu ve dolayısıyla kendi ortam dosyasını okuduğunu unutmayın.
[centos@centos t]$ echo $$
2610
[centos@centos t]$ export SPIDEY=NIKHIL
[centos@centos t]$ printenv | grep SPIDEY
SPIDEY=NIKHIL
[centos@centos t]$
terminal2: aynı ana bilgisayarda - yukarıdaki değişkenin ayarlandığı aynı kabuk içinde başlatmayın, ayrı olarak terminali başlatın.
[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
bir bash oturumu (pid xxxx) içinde, daha sonra yapılacak cat /proc/xxxx/environ | tr \\0 \\n
diğer bash en oturumda ve ben görmüyorum foo
.
gdb
, ancak hala referans yok. Hafızadaki ortam değişkenleri bloğu, bir değişiklik olduğunda ve proc dosya sisteminde kendi işleminin çevre dosyasına yansıtmadığında yeniden tahsis edilir, ancak bununla birlikte alt işlem tarafından miras alınmasına izin verilir. Bu, çatal olduğunda iç detayların bilinmesi daha kolay olabilir, alt süreç nasıl olduğu gibi kopyalanır.
Peki, aşağıdaki yazarın gerçek niyetleri ile ilgili değildir, ancak gerçekten "OKUYUN" /proc/<pid>/environ
istiyorsanız, deneyebilirsiniz
strings /proc/<pid>/environ
cat
ondan daha iyi .
strings
. Basit tut.
xargs --null
.
tr '\0' '\n' < /proc/$$/environ | ...