หากกระบวนการสืบทอดสภาพแวดล้อมของผู้ปกครองทำไมเราถึงต้องส่งออก


72

ฉันอ่านที่นี่ว่าวัตถุประสงค์ของexportเชลล์คือการทำให้ตัวแปรพร้อมใช้งานสำหรับกระบวนการย่อยที่เริ่มต้นจากเชลล์

อย่างไรก็ตามฉันได้อ่านที่นี่และที่นี่ว่า"กระบวนการสืบทอดสภาพแวดล้อมของพวกเขาจากผู้ปกครองของพวกเขา (กระบวนการที่เริ่มต้นพวกเขา)"

หากเป็นกรณีนี้เราจำเป็นต้องทำexportอย่างไร ฉันพลาดอะไรไป

ตัวแปรเชลล์ไม่ได้เป็นส่วนหนึ่งของสภาพแวดล้อมโดยปริยายหรือไม่? อะไรคือความแตกต่าง?

คำตอบ:


74

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

a=1 b=2
export b

ส่งผลให้เชลล์ปัจจุบันรู้ว่า$aขยายเป็น 1 และ$b2 แต่กระบวนการย่อยจะไม่รู้อะไรเลยaเพราะมันไม่ได้เป็นส่วนหนึ่งของสภาพแวดล้อม (แม้แต่ในเชลล์ปัจจุบัน)

เครื่องมือที่มีประโยชน์:

  • set: มีประโยชน์สำหรับการดูพารามิเตอร์ของเชลล์ปัจจุบัน, export-or-not
  • set -k: ตั้งค่าargs ที่กำหนดในสภาพแวดล้อม พิจารณาf() { set -k; env; }; f a=1
  • set -a: บอกเชลล์ให้ใส่ชื่อใด ๆ ที่ตั้งค่าไว้ในสภาพแวดล้อม ชอบใส่exportก่อนทุกงาน ที่เป็นประโยชน์สำหรับไฟล์ในขณะที่.envset -a; . .env; set +a
  • export: บอกเชลล์เพื่อใส่ชื่อในสภาพแวดล้อม การส่งออกและการมอบหมายเป็นการดำเนินการที่แตกต่างกันสองอย่าง
  • env: ในฐานะที่เป็นคำสั่งภายนอกenvสามารถบอกคุณได้เฉพาะเกี่ยวกับสภาพแวดล้อมที่สืบทอดดังนั้นจึงเป็นประโยชน์สำหรับการตรวจสอบสติ
  • env -i: มีประโยชน์สำหรับการล้างสภาพแวดล้อมก่อนที่จะเริ่มกระบวนการย่อย

ทางเลือกอื่น ๆexport:

  1. name=val command # Assignment ก่อนที่คำสั่งจะเอ็กซ์ปอร์ตชื่อนั้นไปยังคำสั่ง
  2. declare/local -x name # ชื่อการส่งออกมีประโยชน์อย่างยิ่งในฟังก์ชั่นเชลล์เมื่อคุณต้องการหลีกเลี่ยงการเปิดเผยชื่อในขอบเขตภายนอก
  3. set -a # ส่งออกทุกงานที่ได้รับมอบหมายดังต่อไปนี้

3
set -kเพื่อให้สามารถใช้cmd ENVVAR=valueในสถานที่ของENVVAR=value cmdที่จะไม่ทำงานในตัวอย่างของคุณจนกว่าดำเนินการก่อนที่จะกล่าวอ้างset -k fนอกจากนี้ยังมีหอยไม่กี่ตัวที่รองรับในปัจจุบันและรองรับความเข้ากันได้แบบย้อนหลังกับเชลล์เป้าหมายเท่านั้น ในเชลล์ Bourne (หรือ Korn) ที่ไม่สามารถใช้งานได้ และเนื่องจากมันมีผลกระทบกับการแยกวิเคราะห์เชลล์จึงต้องมีผลบังคับใช้ในเวลาที่เชลล์อ่านโค้ดที่ใช้งานที่นั่น
Stéphane Chazelas

1
คุณอาจต้องการพูดถึงset -a
Stéphane Chazelas

24

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

การใช้exportคุณบอกเชลล์เพื่อเพิ่มตัวแปรเชลล์ให้กับสภาพแวดล้อม คุณสามารถทดสอบโดยใช้printenv(ซึ่งเพิ่งพิมพ์สภาพแวดล้อมstdoutของมันเนื่องจากเป็นกระบวนการเด็กที่คุณเห็นผลของexportตัวแปรไอเอ็นจี):

#!/bin/sh

MYVAR="my cool variable"

echo "Without export:"
printenv | grep MYVAR

echo "With export:"
export MYVAR
printenv | grep MYVAR

6

ตัวแปรที่ถูกส่งออกเมื่อเป็นส่วนหนึ่งของสภาพแวดล้อม PATHถูกส่งออกในเชลล์ตัวเองในขณะที่ตัวแปรที่กำหนดเองสามารถส่งออกได้ตามต้องการ ใช้รหัสการตั้งค่าบางอย่าง:

$ cat subshell.sh 
#!/usr/bin/env bash
declare | grep -e '^PATH=' -e '^foo='

เปรียบเทียบ

$ cat test.sh 
#!/usr/bin/env bash
export PATH=/bin
export foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test.sh 
PATH=/bin
foo=bar
PATH=/bin
foo=bar

กับ

$ cat test2.sh 
#!/usr/bin/env bash
PATH=/bin
foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test2.sh 
PATH=/bin
foo=bar
PATH=/bin

เนื่องจากfooไม่ได้ถูกส่งออกโดยเชลล์และtest2.shไม่เคยส่งออกมันจึงไม่ได้เป็นส่วนหนึ่งของสภาพแวดล้อมsubshell.shในการทำงานครั้งล่าสุด

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