ฉันสนใจที่จะตั้งค่าตัวแปรสภาพแวดล้อมของเชลล์อินสแตนซ์หนึ่งจากอีกอันหนึ่ง ฉันจึงตัดสินใจทำการวิจัย หลังจากอ่านคำถามจำนวนหนึ่งเกี่ยวกับเรื่องนี้ฉันตัดสินใจที่จะทดสอบ
ผมสองกระบอกเปลือกหอย A และ B (PID 420) zsh
ทั้งการทำงาน จาก AI เชลล์วิ่งต่อไปนี้
sudo gdb -p 420
(gdb) call setenv("FOO", "bar", 1)
(gdb) detach
จาก shell B เมื่อฉันรันenv
ฉันเห็นตัวแปร FOO ถูกตั้งค่าด้วยค่าบาร์ นี่ทำให้ฉันคิดว่า FOO ได้รับการเริ่มต้นได้สำเร็จในสภาพแวดล้อมของ shell B อย่างไรก็ตามถ้าฉันพยายามพิมพ์ FOO ฉันจะได้รับบรรทัดว่างซึ่งหมายความว่าไม่ได้ตั้งค่าไว้ สำหรับฉันมันรู้สึกเหมือนมีความขัดแย้งที่นี่
สิ่งนี้ได้รับการทดสอบทั้งในระบบ Arch GNU / Linux ของฉันและ Ubuntu VM ฉันยังทดสอบสิ่งนี้bash
ว่าตัวแปรไม่ได้แสดงใน env แม้ว่ามันจะน่าผิดหวังสำหรับฉัน แต่ก็สมเหตุสมผลถ้าเชลล์เก็บสำเนาของสภาพแวดล้อมในเวลาที่วางไข่และใช้สิ่งนั้นเท่านั้น (ซึ่งถูกเสนอให้กับหนึ่งในคำถามที่เชื่อมโยง) นี่ยังไม่ตอบว่าทำไมถึงzsh
เห็นตัวแปร
ทำไมการส่งออกของecho $FOO
ว่างเปล่า
แก้ไข
หลังจากป้อนข้อมูลในความคิดเห็นฉันตัดสินใจทำการทดสอบอีกเล็กน้อย ผลลัพธ์สามารถดูได้ในตารางด้านล่าง ในคอลัมน์แรกคือเชลล์ที่FOO
ตัวแปรถูกฉีดเข้าไป แถวแรกมีคำสั่งที่สามารถเห็นเอาต์พุตได้ด้านล่าง ตัวแปรFOO
ถูกฉีดโดยใช้: sudo gdb -p 420 -batch -ex 'call setenv("FOO", "bar", 1)'
. คำสั่งเฉพาะสำหรับ zsh: zsh -c '...'
ถูกทดสอบโดยใช้ bash ผลลัพธ์ที่ได้เหมือนกันเอาท์พุทของพวกเขาถูกละเว้นสำหรับความกะทัดรัด
Arch GNU / Linux, zsh 5.3.1, ทุบตี 4.4.12 (1)
| | env | grep FOO | echo $FOO | zsh -c 'env | grep FOO' | zsh -c 'echo $FOO' | After export FOO |
|------|------------------|-----------|---------------------------|----------------------|-----------------------------------|
| zsh | FOO=bar | | FOO=bar | bar | No Change |
| bash | | bar | | | Value of FOO visible in all tests |
Ubuntu 16.04.2 LTS, zsh 5.1.1, ทุบตี 4.3.48 (1)
| | env | grep FOO | echo $FOO | zsh -c 'env | grep FOO' | zsh -c 'echo $FOO' | After export FOO |
|------|------------------|-----------|---------------------------|----------------------|-----------------------------------|
| zsh | FOO=bar | | FOO=bar | bar | No Change |
| bash | | bar | | | Value of FOO visible in all tests |
ด้านบนดูเหมือนว่าจะบ่งบอกว่าผลลัพธ์ที่มีการกระจายไม่เชื่อเรื่องพระเจ้า สิ่งนี้ไม่ได้บอกอะไรมากไปกว่าzsh
และbash
จัดการกับการตั้งค่าตัวแปรต่างกัน นอกจากนี้export FOO
ยังมีพฤติกรรมที่แตกต่างกันมากในบริบทนี้ขึ้นอยู่กับเชลล์ หวังว่าการทดสอบเหล่านี้จะทำให้คนอื่นเห็นได้ชัดเจน
env
) จะเห็นสภาพแวดล้อมที่แก้ไข
zsh
ใน GDB ไม่ทำให้มองเห็นได้เป็นตัวแปรเชลล์ แต่ทำให้ส่งผ่านไปยังกระบวนการลูก (เช่น คุณได้สังเกต) ในขณะที่การตั้งค่าหนึ่งสำหรับbash
ไม่ให้มองเห็นเป็นตัวแปรเปลือก แต่ไม่ได้ทำให้มันจะถูกส่งผ่านไปยังกระบวนการที่เด็ก! ดูเหมือนว่า zsh และ bash ใช้กลยุทธ์ที่แตกต่างกันสำหรับการจัดการตัวแปรด้วยการติดตาม zsh ตัวแปรที่ไม่ใช่สภาพแวดล้อมและทุบตีเก็บทุกอย่างในสภาพแวดล้อมที่มันฆ่าเชื้อเมื่อเปิดตัวเด็ก (ไม่ใช่ subshell)
export FOO
ในbash
?
zsh -c 'echo $FOO'
(ใช้เครื่องหมายคำพูดเดี่ยว!) แทน? คุณเห็นมันไหม?