GNU/Linux >> Belajar Linux >  >> Linux

Cara membaca variabel lingkungan dari suatu proses

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] ~]$ 

Linux
  1. Variabel Lingkungan Linux:Cara Membaca dan Mengatur di VPS Linux

  2. Cara mengatur variabel lingkungan Linux dengan Ansible

  3. Bagaimana cara mencetak variabel lingkungan yang tampaknya tersembunyi?

  1. Cara Mengatur/Membuat Variabel Lingkungan dan Shell di Linux

  2. Bagaimana Melewati Variabel Lingkungan ke Docker Containers

  3. Cara Mengatur, Mendaftar, dan Menghapus Variabel Lingkungan di Linux

  1. Bagaimana Anda memberi su variabel lingkungan pengguna saat ini

  2. Bagaimana saya bisa membuat R membaca variabel lingkungan saya?

  3. Betapa tidak disetelnya banyak variabel lingkungan