Linux /proc/<pid>/environ
tidak memperbarui (seperti yang saya mengerti, file tersebut mengandung lingkungan awal dari proses).
Bagaimana saya bisa membaca lingkungan proses saat ini ?
sumber
Linux /proc/<pid>/environ
tidak memperbarui (seperti yang saya mengerti, file tersebut mengandung lingkungan awal dari proses).
Bagaimana saya bisa membaca lingkungan proses saat ini ?
/proc/$pid/environ
tidak memperbarui jika proses mengubah lingkungannya sendiri. Tetapi banyak program tidak perlu repot mengubah lingkungannya sendiri, karena ini sedikit tidak berguna: lingkungan program tidak terlihat melalui saluran normal, hanya melalui /proc
dan ps
, dan bahkan tidak setiap varian unix memiliki fitur semacam ini, sehingga aplikasi tidak bergantung di atasnya.
Sejauh menyangkut kernel, lingkungan hanya muncul sebagai argumen dari execve
panggilan sistem yang memulai program. Linux mengekspos area dalam memori melalui /proc
, dan beberapa program memperbarui area ini sementara yang lain tidak. Secara khusus, saya tidak berpikir shell memperbarui area ini. Karena area memiliki ukuran tetap, tidak mungkin untuk menambahkan variabel baru atau mengubah panjang nilai.
PATH=foo
di shell tidak berarti shell akan dimodifikasi*envp
. Dalam beberapa shell, yang hanya memperbarui struktur data internal, dan kode eksekusi program eksternal yang diperbarui*envp
. Lihat diassign_in_env
dalamvariables.c
sumber bash, misalnya.fork
maka libc membuatsys_fork
panggilan menggunakan lingkungan heap yang dialokasikan untuk proses anak.argv
lebih umum tetapi keduanya ada).Anda dapat membaca lingkungan awal suatu proses dari
/proc/<pid>/environ
.Jika suatu proses mengubah lingkungannya, maka untuk membaca lingkungan Anda harus memiliki tabel simbol untuk proses dan menggunakan
ptrace
panggilan sistem (misalnya dengan menggunakangdb
) untuk membaca lingkungan darichar **__environ
variabel global . Tidak ada cara lain untuk mendapatkan nilai variabel apa pun dari proses Linux yang sedang berjalan.Itulah jawabannya. Sekarang untuk beberapa catatan.
Di atas mengasumsikan bahwa prosesnya adalah POSIX compliant, yang berarti bahwa proses mengelola lingkungannya menggunakan variabel global
char **__environ
seperti yang ditentukan dalam Referensi Ref .Lingkungan awal untuk suatu proses dilewatkan 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, setiap skema yang masuk akal untuk memungkinkan perubahan dalam lingkungan proses akan menggunakan heap, di mana memori dalam ukuran sewenang-wenang dapat dialokasikan dan dibebaskan, yang persis seperti yang dilakukan GNUlibc
(glibc
) untuk Anda.Jika proses menggunakan
glibc
, maka itu adalah POSIX compliant, dengan__environ
dideklarasikan diglibc//posix/environ.c
Glibc menginisialisasi__environ
dengan pointer ke memori yangmalloc
berasal dari tumpukan proses, kemudian menyalin lingkungan awal dari tumpukan ke area tumpukan ini. Setiap kali proses menggunakansetenv
fungsi,glibc
lakukanrealloc
untuk menyesuaikan ukuran area yang__environ
menunjuk untuk mengakomodasi nilai atau variabel baru. (Anda dapat mengunduh kode sumber glibc dengangit clone git://sourceware.org/git/glibc.git glibc
). Untuk benar-benar memahami mekanisme ini, Anda juga harus membaca kode Hurd dihurd//init/init.c:frob_kernel_process()
(git clone git: //git.sv.gnu.org/hurd/hurd.git hurd).Sekarang jika proses baru hanya
fork
diedit, tanpaexec
menimpa tumpukan berikutnya , maka argumen dan sihir penyalinan lingkungan dilakukanlinux//kernel/fork.c:do_fork(...)
, di manacopy_process
panggilan rutindup_task_struct
yang mengalokasikan tumpukan proses baru dengan memanggilalloc_thread_info_node
, yang memanggilsetup_thread_stack
(linux//include/linux/sched.h
) untuk proses baru menggunakanalloc_thread_info_node
.Akhirnya,
__environ
konvensi POSIX adalah konvensi ruang pengguna . Tidak memiliki koneksi dengan apa pun di kernel Linux. Anda dapat menulis program userspace tanpa menggunakanglibc
dan tanpa__environ
global dan kemudian mengelola variabel lingkungan sesuka Anda. Tidak ada yang akan menahan Anda untuk melakukan ini tetapi Anda harus menulis fungsi manajemen lingkungan Anda sendiri (setenv
/getenv
) dan pembungkus Anda sendiri untuksys_exec
dan kemungkinan tidak ada yang akan bisa menebak di mana Anda menempatkan perubahan pada lingkungan Anda.sumber
/proc/[pid]/
tampaknya memiliki penyandian aneh (orang lain mungkin tahu apa dan mengapa). Bagi saya, cukupcat environ
mencetak variabel lingkungan dalam format yang sangat sulit dibaca.cat environ | strings
memecahkan ini untukku.Ini diperbarui ketika 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?atau
atau
Di atas akan mencetak variabel lingkungan dari proses dalam
ps
format output, pemrosesan teks (parsing / filtering) diperlukan untuk melihat variabel lingkungan sebagai daftar.Solaris (tidak ditanyakan, tetapi untuk referensi saya akan posting di sini):
atau
EDIT: / proc / pid /viron tidak diperbarui! Saya berdiri dikoreksi. Proses verifikasi di bawah. Namun, anak-anak dari mana proses tersebut diwariskan mewarisi variabel lingkungan proses dan terlihat di file / proc / self / environment masing-masing. (Gunakan string)
Dengan di dalam shell: di sini xargs adalah proses anak dan karenanya mewarisi variabel lingkungan dan juga tercermin dalam
/proc/self/environ
file -nya .Memeriksa dari sesi lain, di mana terminal / sesi bukanlah proses anak dari shell di mana variabel lingkungan diatur.
Memverifikasi dari terminal / sesi lain pada host yang sama:
terminal1:: Perhatikan bahwa printenv adalah fork'd dan merupakan proses anak dari bash dan karenanya ia membaca file environmentnya sendiri.
terminal2: pada host yang sama - jangan memulai dengan shell yang sama di mana variabel di atas diatur, luncurkan terminal secara terpisah.
sumber
export foo=bar
di sesi satu bash (pid xxxx), kemudian lakukancat /proc/xxxx/environ | tr \\0 \\n
di sesi bash lain dan saya tidak melihatfoo
.gdb
pada pid, tetapi masih tidak ada referensi di sana. Blok variabel lingkungan dalam memori akan dialokasikan kembali setiap kali ada perubahan dan tidak mencerminkan dalam file lingkungan prosesnya sendiri dalam sistem file proc, tetapi bagaimanapun memungkinkan untuk diwarisi oleh proses anak. Itu berarti ini bisa menjadi lebih mudah untuk mengetahui detail intrinsik ketika garpu terjadi, bagaimana proses anak mendapat variabel lingkungan seperti apa adanya.Nah berikut ini tidak terkait dengan niat sebenarnya penulis, tetapi jika Anda benar-benar ingin "BACA"
/proc/<pid>/environ
, Anda dapat mencobamana yang lebih baik dari
cat
itu.sumber
strings
. Tetap sederhana.xargs --null
.tr '\0' '\n' < /proc/$$/environ | ...