ลินุกซ์/proc/<pid>/environ
ไม่อัปเดต (ตามที่ฉันเข้าใจว่าไฟล์มีสภาพแวดล้อมเริ่มต้นของกระบวนการ)
ฉันจะอ่านสภาพแวดล้อมปัจจุบันของกระบวนการได้อย่างไร
ลินุกซ์/proc/<pid>/environ
ไม่อัปเดต (ตามที่ฉันเข้าใจว่าไฟล์มีสภาพแวดล้อมเริ่มต้นของกระบวนการ)
ฉันจะอ่านสภาพแวดล้อมปัจจุบันของกระบวนการได้อย่างไร
คำตอบ:
/proc/$pid/environ
จะอัปเดตหากกระบวนการเปลี่ยนสภาพแวดล้อมของตนเอง แต่หลายโปรแกรมไม่รำคาญสภาพแวดล้อมที่เปลี่ยนแปลงตัวเองเพราะมันเป็นบิตไม่มีจุดหมาย: สภาพแวดล้อมของโปรแกรมไม่สามารถมองเห็นผ่านช่องทางปกติเพียงผ่าน/proc
และps
และแม้ไม่ทุกตัวแปรยูนิกซ์มีชนิดของคุณลักษณะนี้เพื่อให้การใช้งานที่ไม่ต้องพึ่งพา บนมัน
เท่าที่เคอร์เนลเกี่ยวข้องสิ่งแวดล้อมจะปรากฏขึ้นเป็นอาร์กิวเมนต์ของการexecve
เรียกระบบที่เริ่มต้นโปรแกรมเท่านั้น Linux แสดงพื้นที่ในหน่วยความจำผ่าน/proc
และบางโปรแกรมอัพเดตพื้นที่นี้ในขณะที่บางโปรแกรมไม่ทำ โดยเฉพาะอย่างยิ่งฉันไม่คิดว่าเชลล์จะอัพเดทพื้นที่นี้ เนื่องจากพื้นที่มีขนาดคงที่จึงไม่สามารถเพิ่มตัวแปรใหม่หรือเปลี่ยนความยาวของค่าได้
PATH=foo
ในเปลือกหอยบางที่การปรับปรุงเพียงโครงสร้างข้อมูลภายในและก็เป็นโค้ดโปรแกรมภายนอกว่าการปรับปรุง*envp
*envp
ดูassign_in_env
ในvariables.c
แหล่งทุบตีเช่น
fork
ดังนั้น libc จะทำการsys_fork
โทรโดยใช้สภาพแวดล้อมที่จัดสรรฮีปสำหรับกระบวนการย่อย
argv
เป็นเรื่องปกติมากขึ้น แต่มีอยู่ทั้งคู่)
คุณสามารถอ่านสภาพแวดล้อมเริ่มต้นของกระบวนการ/proc/<pid>/environ
ได้
หากกระบวนการเปลี่ยนแปลงสภาพแวดล้อมดังนั้นเพื่อที่จะอ่านสภาพแวดล้อมคุณต้องมีตารางสัญลักษณ์สำหรับกระบวนการและใช้การptrace
เรียกของระบบ (ตัวอย่างเช่นโดยใช้gdb
) เพื่ออ่านสภาพแวดล้อมจากchar **__environ
ตัวแปรโกลบอล ไม่มีวิธีอื่นในการรับค่าของตัวแปรใด ๆ จากกระบวนการ Linux ที่ทำงานอยู่
นั่นคือคำตอบ ตอนนี้สำหรับบันทึกย่อบางส่วน
ดังกล่าวข้างต้นสันนิษฐานว่าเป็นกระบวนการตาม POSIX ซึ่งหมายความว่ากระบวนการจัดการสภาพแวดล้อมของการใช้ตัวแปรทั่วโลกchar **__environ
ตามที่ระบุไว้ในRef Spec
สภาพแวดล้อมเริ่มต้นสำหรับกระบวนการถูกส่งผ่านไปยังกระบวนการในบัฟเฟอร์ความยาวคงที่บนสแต็กของกระบวนการ (กลไกปกติที่เป็นlinux//fs/exec.c:do_execve_common(...)
เช่นนี้) เนื่องจากขนาดของบัฟเฟอร์ถูกคำนวณให้มีขนาดไม่เกินขนาดที่ต้องการสำหรับสภาพแวดล้อมเริ่มต้นคุณไม่สามารถเพิ่มตัวแปรใหม่โดยไม่ต้องลบตัวแปรที่มีอยู่หรือทำให้สแต็กแตก ดังนั้นรูปแบบที่สมเหตุสมผลใด ๆ ที่จะอนุญาตให้มีการเปลี่ยนแปลงในสภาพแวดล้อมของกระบวนการจะใช้ heap ซึ่งหน่วยความจำในขนาดที่กำหนดเองสามารถจัดสรรและปลดปล่อยได้ซึ่งเป็นสิ่งที่ GNU libc
( glibc
) ทำเพื่อคุณ
หากกระบวนการใช้glibc
แล้วมันเป็นไปตาม POSIX โดยมี__environ
การประกาศในglibc//posix/environ.c
Glibc เริ่มต้น__environ
ด้วยตัวชี้ไปยังหน่วยความจำที่มันmalloc
มาจากกองของกระบวนการจากนั้นคัดลอกสภาพแวดล้อมเริ่มต้นจากสแต็กลงในพื้นที่กองนี้ ทุกครั้งที่กระบวนการใช้setenv
ฟังก์ชั่นglibc
ทำrealloc
เพื่อปรับขนาดของพื้นที่ที่__environ
ชี้ไปเพื่อรองรับค่าหรือตัวแปรใหม่ (คุณสามารถดาวน์โหลดซอร์สโค้ด glibc ด้วยgit clone git://sourceware.org/git/glibc.git glibc
) ในการทำความเข้าใจกลไกคุณจะต้องอ่านรหัส Hurd ในhurd//init/init.c:frob_kernel_process()
(git clone git: //git.sv.gnu.org/hurd/hurd.git hurd)
ตอนนี้ถ้ากระบวนการใหม่เป็นเพียงfork
ed โดยไม่ต้องต่อมาexec
เขียนทับกองแล้วอาร์กิวเมนต์และสภาพแวดล้อมในการคัดลอกมายากลจะทำในlinux//kernel/fork.c:do_fork(...)
ที่copy_process
โทรประจำdup_task_struct
ที่สแต็จัดสรรกระบวนการใหม่โดยการโทรalloc_thread_info_node
ที่โทรsetup_thread_stack
( linux//include/linux/sched.h
) alloc_thread_info_node
สำหรับกระบวนการใหม่โดยใช้
สุดท้าย POSIX __environ
ประชุมเป็นผู้ใช้พื้นที่การประชุม มันไม่มีส่วนเกี่ยวข้องใด ๆ กับเคอร์เนล Linux คุณสามารถเขียนโปรแกรม userspace โดยไม่ต้องใช้glibc
และไม่มี__environ
โกลบอลจากนั้นจัดการตัวแปรสภาพแวดล้อมตามที่คุณต้องการ ไม่มีใครจะจับกุมคุณในการทำเช่นนี้ แต่คุณจะต้องเขียนฟังก์ชั่นการจัดการสภาพแวดล้อมของคุณ ( setenv
/ getenv
) และสิ่งห่อหุ้มของคุณเองsys_exec
และมีโอกาสที่จะไม่มีใครสามารถเดาได้ว่าคุณใส่อะไรไว้ในสภาพแวดล้อมของคุณ
/proc/[pid]/
ดูเหมือนจะมีการเข้ารหัสแปลก ๆ (บางคนอาจรู้ว่าอะไรและเพราะอะไร) สำหรับฉันเพียงcat environ
พิมพ์ตัวแปรสภาพแวดล้อมในรูปแบบที่อ่านยาก cat environ | strings
แก้ไขปัญหานี้ให้ฉัน
มันถูกอัพเดตเป็นและเมื่อกระบวนการได้มา / ลบตัวแปรสภาพแวดล้อม คุณมีการอ้างอิงซึ่งระบุว่าenviron
ไฟล์ไม่ได้รับการปรับปรุงสำหรับกระบวนการในไดเรกทอรีกระบวนการภายใต้ระบบไฟล์ / proc หรือไม่
xargs --null --max-args=1 echo < /proc/self/environ
หรือ
xargs --null --max-args=1 echo < /proc/<pid>/environ
หรือ
ps e -p <pid>
ด้านบนจะพิมพ์ตัวแปรสภาพแวดล้อมของกระบวนการในps
รูปแบบผลลัพธ์การประมวลผลข้อความ (การแยกวิเคราะห์ / การกรอง) จำเป็นต้องใช้เพื่อดูตัวแปรสภาพแวดล้อมเป็นรายการ
Solaris (ไม่ถาม แต่สำหรับการอ้างอิงฉันจะโพสต์ที่นี่):
/usr/ucb/ps -wwwe <pid>
หรือ
pargs -e <pid>
แก้ไข: / proc / pid / environ ไม่ได้รับการอัพเดต! ฉันยืนแก้ไขแล้ว กระบวนการตรวจสอบอยู่ด้านล่าง อย่างไรก็ตามเด็ก ๆ ที่กระบวนการนั้นจะแยกสืบทอดตัวแปรสภาพแวดล้อมของกระบวนการและมันสามารถมองเห็นได้ในไฟล์ / proc / self / environ ที่เกี่ยวข้อง (ใช้สตริง)
ในเชลล์: นี่คือ xargs เป็นกระบวนการลูกและสืบทอดตัวแปรสภาพแวดล้อมและยังสะท้อนให้เห็นใน/proc/self/environ
ไฟล์
[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]$
ตรวจสอบจากเซสชันอื่นโดยที่เทอร์มินัล / เซสชันไม่ใช่กระบวนการย่อยของเชลล์ที่ตั้งค่าตัวแปรสภาพแวดล้อม
การตรวจสอบจากเทอร์มินัล / เซสชันอื่นบนโฮสต์เดียวกัน:
terminal1::โปรดทราบว่า printenv เป็น fork'd และเป็นกระบวนการลูกของ bash และด้วยเหตุนี้มันจึงอ่านไฟล์สภาพแวดล้อมของตัวเอง
[centos@centos t]$ echo $$
2610
[centos@centos t]$ export SPIDEY=NIKHIL
[centos@centos t]$ printenv | grep SPIDEY
SPIDEY=NIKHIL
[centos@centos t]$
เทอร์มินัล 2:บนโฮสต์เดียวกัน - อย่าเปิดมันด้วยในเชลล์เดียวกันที่ตั้งค่าตัวแปรข้างต้นให้เรียกใช้เทอร์มินัลแยกกัน
[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
ในช่วงหนึ่งของการทุบตี (xxxx PID) แล้วทำในเซสชั่นทุบตีอื่นและผมไม่เห็นcat /proc/xxxx/environ | tr \\0 \\n
foo
gdb
กับ pid แต่ก็ยังไม่มีการอ้างอิง ตัวแปรสภาพแวดล้อมบล็อกในหน่วยความจำจะได้รับการจัดสรรใหม่เมื่อใดก็ตามที่มีการเปลี่ยนแปลงและไม่ได้สะท้อนให้เห็นในไฟล์ environ 'กระบวนการของตัวเองในระบบไฟล์ proc แต่ช่วยให้ได้รับการสืบทอดโดยกระบวนการเด็ก ซึ่งหมายความว่าสิ่งนี้จะง่ายต่อการรู้รายละเอียดที่แท้จริงเมื่อ fork เกิดขึ้นกระบวนการลูกได้รับการคัดลอกตัวแปรสภาพแวดล้อมอย่างไร
ต่อไปนี้ไม่เกี่ยวข้องกับความตั้งใจที่แท้จริงของผู้เขียน แต่ถ้าคุณต้องการ "อ่าน" จริงๆ/proc/<pid>/environ
คุณอาจลอง
strings /proc/<pid>/environ
ซึ่งดีกว่าcat
มัน
strings
สำหรับ ง่าย ๆ เข้าไว้.
xargs --null
VS
tr '\0' '\n' < /proc/$$/environ | ...