มีวิธีเปลี่ยนตัวแปรสภาพแวดล้อมของกระบวนการอื่นใน Unix หรือไม่?


106

ใน Unix มีวิธีใดบ้างที่กระบวนการหนึ่งสามารถเปลี่ยนแปลงตัวแปรสภาพแวดล้อมของอีกกระบวนการหนึ่ง (สมมติว่าพวกเขาทั้งหมดถูกเรียกใช้โดยผู้ใช้คนเดียวกัน) วิธีแก้ปัญหาทั่วไปจะดีที่สุด แต่ถ้าไม่แล้วกรณีเฉพาะที่คนหนึ่งเป็นลูกของอีกฝ่ายล่ะ?

แก้ไข: แล้วทาง gdb ล่ะ


สิ่งนี้ทำให้ฉันรู้สึกแย่มากกว่าน่าเกลียด ปัญหาที่แท้จริงที่คุณต้องการแก้ไขคืออะไร?
Jens

1
ตัวอย่าง: ฉันต้องการกำหนดตัวแปรสภาพแวดล้อมเพื่อให้ทุกแอปใหม่ที่เปิดตัวโดย UI จะได้รับมัน ฉันไม่รู้วิธีการใด ๆ เลยนอกจากการกำหนดตัวแปรในสคริปต์เริ่มต้นและ RE-LOGIN อย่างไรก็ตามฉันไม่ต้องการเข้าสู่ระบบอีกครั้ง แต่เพียงกำหนดตัวแปรในเซสชันปัจจุบันเพื่อให้แอปใหม่ได้รับ - โดยไม่ต้องออกจากระบบ UI
AlikElzin-kilaka

คำตอบ:


144

ผ่าน gdb:

(gdb) attach process_id

(gdb) call putenv ("env_var_name=env_var_value")

(gdb) detach

นี่เป็นการแฮ็กที่ค่อนข้างน่ารังเกียจและควรทำในบริบทของสถานการณ์การดีบักเท่านั้น


8
ดูเหมือนว่าคุณสามารถเปลี่ยนสภาพแวดล้อมของกระบวนการได้อย่างแท้จริงหากคุณแนบกับกระบวนการตามที่ GDB ทำแล้วแยกออก ดูเหมือนว่ามันจะเป็นไปได้ที่จะเขียนโปรแกรมที่ทำเพียงแค่นี้
เสียใจ

3
"ดูเหมือนว่ามันจะเป็นไปได้ที่จะเขียนโปรแกรมที่ทำเพียงแค่นี้" อันที่จริง .. มันคือ
L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳

2
มันยังทำงานบน Windows โดยใช้ cygwin สำหรับกระบวนการที่ไม่ได้รวบรวมโดยใช้ cygwin!
Juan Carlos Muñoz

12
โปรดทราบว่าสิ่งนี้ใช้ได้เฉพาะเมื่อกระบวนการไม่ได้แคชค่าไว้อย่างถาวรหลังจาก getenv ก่อนหน้านี้
An̲̳̳drew

2
ในบางระบบ gdb อาจให้ข้อผิดพลาดต่อไปนี้: 'putenv' has unknown return type; cast the call to its declared return type; ในกรณีเหล่านี้คุณควรเปลี่ยนputenvคำเรียกนี้:call (int) putenv ("env_var_name=env_var_value")
Emir Uner

22

คุณอาจทำได้ในทางเทคนิค (ดูคำตอบอื่น ๆ ) แต่อาจไม่ช่วยคุณ

โปรแกรมส่วนใหญ่จะคาดหวังว่า env vars ไม่สามารถเปลี่ยนแปลงได้จากภายนอกหลังจากเริ่มต้นดังนั้นส่วนใหญ่อาจจะอ่าน vars ที่พวกเขาสนใจเมื่อเริ่มต้นและเริ่มต้นตามนั้น ดังนั้นการเปลี่ยนหลังจากนั้นจะไม่สร้างความแตกต่างเนื่องจากโปรแกรมจะไม่อ่านซ้ำ

หากคุณโพสต์สิ่งนี้เป็นปัญหาที่เป็นรูปธรรมคุณควรใช้แนวทางอื่น ถ้ามันเป็นเพียงแค่ความอยากรู้: คำถามที่ดี :-)


1
กรณีการใช้งานที่พบบ่อยที่สุดที่จะเป็นประโยชน์คือการทำให้กระบวนการย่อยสืบทอดตัวแปรสภาพแวดล้อมใหม่ตัวอย่างเช่นในสภาพแวดล้อมเดสก์ท็อปที่คุณต้องการให้เทอร์มินัลใหม่ใช้ตัวแปรใหม่
Hjulle

13

อย่างมีสาระสำคัญไม่มี หากคุณมีสิทธิ์เพียงพอ (รูทหรือแถวนั้น) และโผล่รอบ ๆ / dev / kmem (หน่วยความจำเคอร์เนล) และคุณได้ทำการเปลี่ยนแปลงสภาพแวดล้อมของกระบวนการและหากกระบวนการอ้างอิงตัวแปรสภาพแวดล้อมอีกครั้งในภายหลัง (นั่นคือกระบวนการ ยังไม่ได้ถ่ายสำเนา env var และไม่ได้ใช้แค่สำเนานั้น) บางทีถ้าคุณโชคดีและฉลาดลมก็พัดไปในทิศทางที่ถูกต้องและระยะของดวงจันทร์ก็ถูกต้องบางที คุณอาจประสบความสำเร็จบางอย่าง


2
ฉันไม่ได้รับคำตอบ
AlikElzin-kilaka

@kilaka: คำสำคัญคือคนที่สอง - ไม่มี ส่วนที่เหลือของคำตอบที่จะบอกว่าถ้าคุณมีสิทธิ์ root หรือกำลังทำงานดีบักแล้วบางทีคุณสามารถทำมัน แต่สำหรับวัตถุประสงค์ในทางปฏิบัติทุกคำตอบคือไม่มี
Jonathan Leffler

คุณมีเชลล์สคริปต์ทำงานอยู่ คุณต้องการเปลี่ยนสภาพแวดล้อมในการปกครองเชลล์สคริปต์ของคุณ ... ดังนั้นการเปิดตัวเชลล์สคริปต์gdbในการปกครองและสคริปต์เข้าทำทำให้การเปลี่ยนแปลงและการทำงานโดยไม่ต้องล้มการปกครอง โอเค - คุณอาจทำได้ แต่ไม่ใช่สิ่งที่คุณต้องทำเป็นประจำ สำหรับวัตถุประสงค์ในทางปฏิบัติดังนั้นคำตอบยังคงไม่มี คำตอบที่เหลือครอบคลุมถึงทางเลือกที่เป็นไปได้ในทางทฤษฎีซึ่งค่อนข้างทำไม่ได้
Jonathan Leffler

7

อ้างถึง Jerry Peek:

คุณไม่สามารถสอนเทคนิคใหม่ให้กับสุนัขตัวเก่าได้

สิ่งเดียวที่คุณทำได้คือเปลี่ยนตัวแปรสภาพแวดล้อมของกระบวนการลูกก่อนเริ่มต้น: ได้รับสำเนาของสภาพแวดล้อมหลักขออภัย

ดูรายละเอียดได้ที่http://www.unix.com.ua/orelly/unix/upt/ch06_02.htm

เพียงแสดงความคิดเห็นเกี่ยวกับคำตอบเกี่ยวกับการใช้ / proc ภายใต้ linux / proc ได้รับการสนับสนุน แต่ใช้งานไม่ได้คุณไม่สามารถเปลี่ยน/proc/${pid}/environไฟล์ได้แม้ว่าคุณจะรูทก็ตามมันเป็นแบบอ่านอย่างเดียว


ซึ่งยังคงทิ้งคำถามไว้: ค่า env var ถูกเก็บไว้ที่ไหน? เคอร์เนลนั้นทำหรือไม่? หรือเชลล์เก็บค่าและ / proc / <pid> / environ ได้รับจากที่นั่นหรือไม่
oliver

นี่คือรายละเอียดการใช้งานและอาจเป็นคำถามที่ดี (แยกต่างหาก) ฉันคิดว่า UNIX ทุกเครื่องใช้วิธีการจัดเก็บข้อมูลของตัวเอง แต่ทุกคนมีพฤติกรรมที่อธิบายไว้ข้างต้นซึ่งเป็นส่วนหนึ่งของข้อกำหนด
Davide

7

ฉันคิดได้ว่าวิธีการทำแบบนั้นค่อนข้างมีการเปลี่ยนแปลงและมันจะใช้ไม่ได้กับกระบวนการตามอำเภอใจ

สมมติว่าคุณเขียนไลบรารีที่ใช้ร่วมกันของคุณเองซึ่งใช้ 'char * getenv' จากนั้นคุณตั้งค่า env "LD_PRELOAD" หรือ "LD_LIBRARY_PATH" vars เพื่อให้ทั้งสองกระบวนการของคุณทำงานด้วยไลบรารีที่แชร์ของคุณที่โหลดไว้ล่วงหน้า

ด้วยวิธีนี้คุณจะสามารถควบคุมโค้ดของฟังก์ชัน 'getenv' ได้เป็นหลัก จากนั้นคุณสามารถใช้กลอุบายที่น่ารังเกียจได้ทุกประเภท 'getenv' ของคุณสามารถปรึกษาไฟล์ config ภายนอกหรือเซ็กเมนต์ SHM สำหรับค่าทางเลือกของ env vars หรือคุณสามารถค้นหา / แทนที่ regexp ตามค่าที่ร้องขอ หรือ ...

ฉันไม่สามารถนึกถึงวิธีง่ายๆในการทำเช่นนั้นสำหรับกระบวนการทำงานโดยพลการ (แม้ว่าคุณจะเป็นรูทก็ตาม) โดยย่อมาจาก dynamic linker (ld-linux.so)


สิ่งนี้ควรทำได้ คุณสามารถมีฐานข้อมูล gdbm เล็กน้อยสำหรับคู่ var = value ฉันมีบางสิ่งที่คล้ายกันสำหรับ malloc ที่stromberg.dnsalias.org/~strombrg/malloc-wrapper
dstromberg

ฉันคิดว่าวิธีนี้ต้องใช้ความคิดล่วงหน้า นอกจากนี้คุณยังต้องระวังอย่านำไปใช้กับกระบวนการมากเกินไปโดยไม่ได้ตั้งใจ
dstromberg

3

หรือรับกระบวนการของคุณเพื่ออัปเดตไฟล์กำหนดค่าสำหรับกระบวนการใหม่จากนั้น:

  • ทำการ kill -HUP ในกระบวนการใหม่เพื่ออ่านไฟล์กำหนดค่าที่อัพเดตหรือ
  • ให้กระบวนการตรวจสอบไฟล์กำหนดค่าสำหรับการอัปเดตเป็นระยะ ๆ หากพบการเปลี่ยนแปลงให้อ่านไฟล์กำหนดค่าอีกครั้ง

2

ไม่เท่าที่ฉันรู้ จริงๆแล้วคุณกำลังพยายามสื่อสารจากกระบวนการหนึ่งไปยังอีกกระบวนการหนึ่งซึ่งเรียกร้องให้ใช้วิธีใดวิธีหนึ่งของ IPC (หน่วยความจำที่ใช้ร่วมกันเซมาโฟร์ซ็อกเก็ต ฯลฯ ) เมื่อได้รับข้อมูลโดยวิธีใดวิธีหนึ่งเหล่านี้คุณสามารถตั้งค่าตัวแปรสภาพแวดล้อมหรือดำเนินการอื่น ๆ ได้โดยตรงมากขึ้น


2

ดูเหมือนว่าputenvจะไม่ทำงานในตอนนี้ แต่setenvทำ ฉันกำลังทดสอบคำตอบที่ยอมรับในขณะที่พยายามตั้งค่าตัวแปรในเชลล์ปัจจุบันโดยไม่ประสบความสำเร็จ

$] sudo gdb -p $$
(gdb) call putenv("TEST=1234")
$1 = 0
(gdb) call (char*) getenv("TEST")
$2 = 0x0
(gdb) detach
(gdb) quit
$] echo "TEST=$TEST"
TEST=

และตัวแปรวิธีการทำงาน:

$] sudo gdb -p $$
(gdb) call (int) setenv("TEST", "1234", 1)
$1 = 0
(gdb) call (char*) getenv("TEST")
$2 = 0x55f19ff5edc0 "1234"
(gdb) detach
(gdb) quit
$] echo "TEST=$TEST"
TEST=1234

1

หาก unix ของคุณรองรับระบบไฟล์ / proc การอ่าน env ก็เป็นเรื่องเล็กน้อย - คุณสามารถอ่านสภาพแวดล้อม commandline และคุณลักษณะอื่น ๆ ของกระบวนการที่คุณเป็นเจ้าของด้วยวิธีนั้น การเปลี่ยนมัน ... ฉันคิดวิธีได้ แต่มันเป็นความคิดที่ไม่ดี

กรณีทั่วไป ... ฉันไม่รู้ แต่ฉันสงสัยว่ามีคำตอบแบบพกพา

(แก้ไข: คำตอบเดิมของฉันถือว่า OP ต้องการอ่าน env ไม่เปลี่ยนแปลง)


อ๊ะแก้ไขคำตอบของฉัน - ฉันสมมติว่าเขาต้องการอ่าน env ไม่ใช่เปลี่ยน
Mike G.

1
อย่าทิ้งฉันไว้ ความคิดที่ไม่ดีของคุณคืออะไร?
raldi

บน Linux ฉันเชื่อว่าคุณอาจจะสามารถเปิด / proc / <pid> / mem read-write สำหรับกระบวนการอื่น ๆ ที่คุณเป็นเจ้าของได้ ... ฉันไม่แน่ใจ การพยายามและยุ่งกับสภาพแวดล้อมจริง ๆ จะเป็นความคิดที่ไม่ดี ดังนั้นฉันไม่แนะนำให้คุณลอง ...
Mike G.

1

UNIX เต็มไปด้วยการสื่อสารระหว่างกระบวนการ ตรวจสอบว่าอินสแตนซ์เป้าหมายของคุณมีบ้างไหม Dbus กำลังกลายเป็นมาตรฐานใน IPC "เดสก์ท็อป"

ฉันเปลี่ยนตัวแปรสภาพแวดล้อมภายในตัวจัดการหน้าต่าง Awesome โดยใช้ไคลเอนต์ที่น่ากลัวด้วยคือ Dbus "ผู้ส่ง" ของรหัส lua


1

ไม่ใช่คำตอบโดยตรง แต่ ... Raymond Chen มีเหตุผล [ที่ใช้ Windows] ในวันอื่น ๆ เท่านั้น : -

... แม้ว่าจะมีวิธีที่ไม่ได้รับการสนับสนุนอย่างแน่นอนในการดำเนินการหรือวิธีที่ทำงานร่วมกับความช่วยเหลือของดีบักเกอร์ แต่ก็ไม่มีสิ่งใดที่ได้รับการสนับสนุนสำหรับการเข้าถึงแบบเป็นโปรแกรมไปยังบรรทัดคำสั่งของกระบวนการอื่นอย่างน้อยก็ไม่มีอะไรมาจากเคอร์เนล ...

นั่นไม่ได้เป็นผลมาจากหลักการของการไม่ติดตามข้อมูลที่คุณไม่ต้องการ เคอร์เนลไม่จำเป็นต้องขอรับบรรทัดคำสั่งของกระบวนการอื่น ใช้บรรทัดคำสั่งส่งผ่านไปยังCreateProcessฟังก์ชันและคัดลอกลงในพื้นที่แอดเดรสของกระบวนการที่กำลังเรียกใช้ในตำแหน่งที่GetCommandLineฟังก์ชันสามารถดึงข้อมูลได้ เมื่อกระบวนการสามารถเข้าถึงบรรทัดคำสั่งของตัวเองได้ความรับผิดชอบของเคอร์เนลจะเสร็จสิ้น

เนื่องจากบรรทัดคำสั่งถูกคัดลอกไปยังพื้นที่แอดเดรสของกระบวนการกระบวนการอาจเขียนไปยังหน่วยความจำที่เก็บบรรทัดคำสั่งและแก้ไขได้ หากเป็นเช่นนั้นบรรทัดคำสั่งเดิมจะหายไปตลอดกาล สำเนาเดียวที่รู้จักถูกเขียนทับ

กล่าวอีกนัยหนึ่งสิ่งอำนวยความสะดวกเคอร์เนลดังกล่าวจะเป็น

  • ใช้งานยาก
  • อาจเป็นปัญหาด้านความปลอดภัย

อย่างไรก็ตามสาเหตุที่เป็นไปได้มากที่สุดก็คือมีกรณีการใช้งานที่ จำกัด สำหรับสถานที่ดังกล่าว

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.