Bir işlemin çevre değişkenleri nasıl okunur


Yanıtlar:


20

/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 /procve pshatta 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 execveprogramı başlatan sistem çağrısının argümanı olarak görünür . Linux hafızada bir alanı açığa çıkarır /procve 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.


Bu nedenle, etkin bir şekilde '* envp (ortam ayarlarına yönelik işaretçiler dizisi) sürecine erişmenin yolu yoktur. @Gilles, lütfen hata ayıklayıcıyı eklemek ve çevre ayarlarına işaretçiler dizisini okumak mümkün olup olmadığını gösterebilir misiniz?
Nikhil Mulley,

2
@Nikhil Elbette, öyle. Fakat sadece PATH=foobir 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_enviçinde variables.cörneğin bash kaynağında.
Gilles 'SO- kötü olmak'

9
@Gilles: Bu cevap en iyi yanıltıcıdır (-1). / Proc / $$ / environment içindeki ortam işlemin yığından okunur. Bkz. Fs / proc / base.c. Bu ilk ortamdır. Asla güncellenmez ve aslında olamaz. Libc setenv'in kullandığı ortam öbek üzerine tahsis edilir ve yığındaki ortamın içeriği ile başlatılır. İşlem libc'leri çağırırsa libc , alt süreç için ayrılan ortamı kullanarak arama forkyapar sys_fork.
Jonathan Ben-Avraham

7
@ JonathanBen-Avraham İlk ortamın herhangi bir kabukta güncellenmediği konusunda haklısın. Ancak bu alan yalnızca Linux altında okunmuyor, durumunu bildirmek için kullanan programlarla karşılaştım (durum raporları aracılığıyla argvdaha yaygın ancak ikisi de var).
Gilles 'SO- kötülük' dur '29

39

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 ptraceiç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 __environbildirilmek suretiyle işlemin glibc//posix/environ.cöbeğinden __environhafızasına bir işaretçi ile başlar malloc, ardından ilk ortamı yığından bu yığın alanına kopyalar. İşlem setenvişlevi her kullandığında, glibca değerini, yeni değeri veya değişkeni barındırmak için işaret realloceden 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 forked ise, execyığı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_processrutinin dup_task_structyeni 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 __environsözleşmesi bir kullanıcı alanı sözleşmesidir. Linux çekirdeğindeki hiçbir şeyle bağlantısı yoktur. Global kullanmadan glibcve kullanmadan bir kullanıcı alanı programı yazabilir __environve 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_execve hiç kimsenin ortamınızdaki değişiklikleri nereye koyacağınızı tahmin edemeyeceği muhtemel.


Dosyaların /proc/[pid]/çoğunun garip bir şifrelemesi var gibi görünüyor (başkası ne ve neden olduğunu biliyor olabilir). Benim cat environiçin çevre değişkenlerini okunması zor bir formatta basardım. cat environ | stringsBunu benim için çözdü.
retrohacker

@retrohacker Bu daha sağlam bir çözüm sunar: askubuntu.com/questions/978711/…
Frank

20

İş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/environdosyası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 ~]$ 

1
Yapmam export foo=barbir bash oturumu (pid xxxx) içinde, daha sonra yapılacak cat /proc/xxxx/environ | tr \\0 \\ndiğer bash en oturumda ve ben görmüyorum foo.

Yukarıdaki cevabı, kabuk içindeki aynı işlemi kontrol eden bir örnekle güncelledim.
Nikhil Mulley,

Haklısın. Düzeltilmiş duruyorum. Teşekkürler. Şimdi, kullanıcı süreç grubunda farklı bir işlemin ortam değişkenlerini kontrol etmek için kılavuzlarımı okuman gerekiyor.
Nikhil Mulley

1
Bir şey daha: Pideye bağlanan ortamı kontrol etmeye çalıştım 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.
Nikhil Mulley

Umarım @Gilles bu fener ışığının bir kısmını buna yakar .. :-)
Nikhil Mulley

7

Peki, aşağıdaki yazarın gerçek niyetleri ile ilgili değildir, ancak gerçekten "OKUYUN" /proc/<pid>/environistiyorsanız, deneyebilirsiniz

strings /proc/<pid>/environ

catondan daha iyi .


1
İçin +1 strings. Basit tut.
Ed Randall

@EdRandall Katılıyorum, bu daha kolay yaklaşım vs gibi hissediyor xargs --null.
Lundberg Per

"Dosya" boş bırakıldı, boş satırları yeni satırla değiştirin ve normal araçlar tekrar çalışır (normal uyarılarla), örneğin:tr '\0' '\n' < /proc/$$/environ | ...
Thor
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.