Anda dapat membaca inisial lingkungan proses dari /proc/<pid>/environ
.
Jika suatu proses berubah lingkungannya, maka untuk membaca lingkungannya anda harus memiliki tabel simbol untuk proses tersebut dan menggunakan ptrace
panggilan sistem (misalnya dengan menggunakan gdb
) untuk membaca lingkungan dari char **__environ
global variabel. Tidak ada cara lain untuk mendapatkan nilai variabel apa pun dari proses Linux yang sedang berjalan.
Itulah jawabannya. Sekarang untuk beberapa catatan.
Hal di atas mengasumsikan bahwa proses sesuai dengan POSIX, artinya proses mengelola lingkungannya menggunakan variabel global char **__environ
sebagaimana ditentukan dalam Ref Spec.
Lingkungan awal untuk suatu proses diteruskan ke proses dalam buffer dengan panjang tetap pada tumpukan proses. (Mekanisme biasa yang melakukan ini adalah linux//fs/exec.c:do_execve_common(...)
.) Karena ukuran buffer dihitung tidak lebih dari ukuran yang diperlukan untuk lingkungan awal, Anda tidak dapat menambahkan variabel baru tanpa menghapus variabel yang ada atau menghancurkan tumpukan. Jadi, skema apa pun yang masuk akal untuk mengizinkan perubahan dalam lingkungan proses akan menggunakan heap, di mana memori dalam ukuran sewenang-wenang dapat dialokasikan dan dibebaskan, yang persis seperti apa yang dilakukan GNU libc
(glibc
) lakukan untuk Anda.
Jika proses menggunakan glibc
, maka sesuai dengan POSIX, dengan __environ
dideklarasikan dalam glibc//posix/environ.c
Glibc menginisialisasi __environ
dengan pointer ke memori yang malloc
s dari tumpukan proses, lalu salin lingkungan awal dari tumpukan ke area tumpukan ini. Setiap kali proses menggunakan setenv
fungsi, glibc
melakukan realloc
untuk menyesuaikan ukuran area yang __environ
menunjuk ke untuk mengakomodasi nilai atau variabel baru. (Anda dapat mengunduh kode sumber glibc dengan git clone git://sourceware.org/git/glibc.git glibc
). Untuk benar-benar memahami mekanismenya, Anda juga harus membaca kode Hurd di hurd//init/init.c:frob_kernel_process()
(git clone git://git.sv.gnu.org/hurd/hurd.git hurd).
Sekarang jika proses baru hanya fork
ed, tanpa exec
berikutnya menimpa tumpukan, lalu sihir penyalinan argumen dan lingkungan dilakukan di linux//kernel/fork.c:do_fork(...)
, di mana copy_process
panggilan rutin dup_task_struct
yang mengalokasikan tumpukan proses baru dengan memanggil alloc_thread_info_node
, yang memanggil setup_thread_stack
(linux//include/linux/sched.h
) untuk proses baru menggunakan alloc_thread_info_node
.
Terakhir, POSIX __environ
konvensi adalah ruang-pengguna Konvensi. Itu tidak ada hubungannya dengan apa pun di kernel Linux. Anda dapat menulis program ruang pengguna tanpa menggunakan glibc
dan tanpa __environ
global dan kemudian kelola variabel lingkungan sesuka Anda. Tidak ada yang akan menangkap Anda karena melakukan ini tetapi Anda harus menulis fungsi manajemen lingkungan Anda sendiri (setenv
/getenv
) dan pembungkus Anda sendiri untuk sys_exec
dan kemungkinan tidak ada yang bisa menebak di mana Anda meletakkan perubahan pada lingkungan Anda.
/proc/$pid/environ
tidak memperbarui jika proses mengubah lingkungannya sendiri. Tetapi banyak program tidak repot-repot mengubah lingkungannya sendiri, karena itu sedikit tidak berguna:lingkungan program tidak terlihat melalui saluran normal, hanya melalui /proc
dan ps
, dan bahkan tidak semua varian unix memiliki fitur semacam ini, sehingga aplikasi tidak mengandalkannya.
Sejauh menyangkut kernel, lingkungan hanya muncul sebagai argumen dari execve
panggilan sistem yang memulai program. Linux mengekspos area di memori melalui /proc
, dan beberapa program memperbarui area ini sementara yang lain tidak. Secara khusus, menurut saya tidak ada shell yang memperbarui area ini. Karena area memiliki ukuran tetap, tidak mungkin menambahkan variabel baru atau mengubah panjang nilai.
Itu diperbarui saat dan ketika proses memperoleh/menghapus variabel lingkungannya. Apakah Anda memiliki referensi yang menyatakan environ
file tidak diperbarui untuk proses dalam direktori prosesnya di bawah /proc filesystem?
xargs --null --max-args=1 echo < /proc/self/environ
atau
xargs --null --max-args=1 echo < /proc/<pid>/environ
atau
ps e -p <pid>
Di atas akan mencetak variabel lingkungan dari proses di ps
format output, pemrosesan teks (parsing/filtering) diperlukan untuk melihat variabel lingkungan sebagai daftar.
Solaris (tidak diminta, tapi untuk referensi saya akan memposting di sini):
/usr/ucb/ps -wwwe <pid>
atau
pargs -e <pid>
EDIT: /proc/pid/environ tidak diperbarui! Saya berdiri dikoreksi. Proses verifikasi ada di bawah. Namun, anak-anak dari mana proses tersebut di-fork akan mewarisi variabel lingkungan proses dan itu terlihat di file /proc/self/environ masing-masing. (Gunakan string)
Dengan di Shell:di sini xargs adalah proses anak dan karenanya mewarisi variabel lingkungan dan juga tercermin dalam /proc/self/environ
berkas.
[[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]$
Memeriksanya dari sesi lain, di mana terminal/sesi bukan proses anak dari shell tempat variabel lingkungan disetel.
Memverifikasi dari terminal/sesi lain di host yang sama:
terminal1: :Perhatikan bahwa printenv adalah fork'd dan merupakan proses anak dari bash dan karenanya membaca file lingkungannya sendiri.
[[email protected] t]$ echo $$
2610
[[email protected] t]$ export SPIDEY=NIKHIL
[[email protected] t]$ printenv | grep SPIDEY
SPIDEY=NIKHIL
[[email protected] t]$
terminal2: pada host yang sama -- jangan luncurkan dengan shell yang sama tempat variabel di atas disetel, luncurkan terminal secara terpisah.
[[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] ~]$