อะไรคือความแตกต่างระหว่างชุดการส่งออกและ env และเมื่อใดที่ฉันควรใช้แต่ละอัน


112

บ่อยครั้งที่ฉันจะทุบตีสคริปต์ทุบตีและทำให้ฉันมีวิธีตั้งค่าตัวแปรสองสามอย่าง:

key=value
env key=value
export key=value

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

ความแตกต่างระหว่างสามวิธีนี้คืออะไรและคุณสามารถยกตัวอย่างให้ฉันเมื่อฉันต้องการใช้แต่ละวิธีเป็นพิเศษได้หรือไม่

เกี่ยวข้องอย่างแน่นอนกับ`ความแตกต่างระหว่าง` VAR = ... 'และ' การส่งออก VAR = ... 'คืออะไร? แต่ฉันต้องการที่จะรู้วิธีที่envเหมาะสมกับเรื่องนี้เช่นกันและตัวอย่างบางส่วนที่แสดงให้เห็นถึงประโยชน์ของแต่ละคนก็ดีเช่นกัน :)


5
โปรดทราบว่าexport key=valueมีการขยายไวยากรณ์และไม่ควรใช้ในสคริปต์แบบพกพา (เช่น#! /bin/sh)
Simon Richter

คำตอบ:


110

ขอให้เราพิจารณาตัวอย่างที่เฉพาะเจาะจง grepคำสั่งใช้ตัวแปรสภาพแวดล้อมที่เรียกว่าGREP_OPTIONSการตั้งค่าตัวเลือกเริ่มต้น

ตอนนี้ ระบุว่าไฟล์test.txtมีบรรทัดต่อไปนี้:

line one
line two

การรันคำสั่งgrep one test.txtจะส่งคืน

line one

หากคุณรัน grep ด้วย-vตัวเลือกมันจะส่งคืนบรรทัดที่ไม่ตรงกันดังนั้นเอาต์พุตจะเป็น

line two

ตอนนี้เราจะพยายามตั้งค่าตัวเลือกด้วยตัวแปรสภาพแวดล้อม

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

    GREP_OPTIONS='-v'
    grep one test.txt

    ผลลัพธ์:

    line one

    เห็นได้ชัดว่าตัวเลือกที่ไม่ได้รับการส่งผ่านไปยัง-vgrep

    คุณต้องการที่จะใช้รูปแบบนี้เมื่อคุณมีการตั้งค่าตัวแปรเพียงเปลือกที่จะใช้เช่นในคุณไม่ต้องการที่จะส่งออกfor i in * ; do$i

  2. อย่างไรก็ตามตัวแปรจะถูกส่งต่อไปยังสภาพแวดล้อมของบรรทัดคำสั่งนั้นโดยเฉพาะดังนั้นคุณสามารถทำได้

    GREP_OPTIONS='-v' grep one test.txt

    ซึ่งจะคืนค่าที่คาดไว้

    line two

    คุณใช้แบบฟอร์มนี้เพื่อเปลี่ยนแปลงสภาพแวดล้อมของอินสแตนซ์เฉพาะของโปรแกรมที่เปิดใช้ชั่วคราว

  3. การส่งออกตัวแปรทำให้ตัวแปรนั้นได้รับการถ่ายทอด:

    export GREP_OPTIONS='-v'
    grep one test.txt

    ส่งคืนตอนนี้

    line two

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

  4. ทั้งหมดนี้ทำในการทุบตี exportเป็นทุบตี builtin; VAR=whateverเป็นไวยากรณ์ทุบตี envในอีกด้านหนึ่งเป็นโปรแกรมในตัวเอง เมื่อenvถูกเรียกสิ่งต่อไปนี้จะเกิดขึ้น:

    1. คำสั่งenvถูกเรียกใช้งานเป็นกระบวนการใหม่
    2. env ปรับเปลี่ยนสภาพแวดล้อมและ
    3. เรียกคำสั่งที่ให้ไว้เป็นอาร์กิวเมนต์ envกระบวนการจะถูกแทนที่ด้วยcommandกระบวนการ

    ตัวอย่าง:

    env GREP_OPTIONS='-v' grep one test.txt

    คำสั่งนี้จะเปิดตัวกระบวนการใหม่สองกระบวนการ: (i) env และ (ii) grep (อันที่จริงแล้วกระบวนการที่สองจะแทนที่กระบวนการแรก) จากมุมมองของgrepกระบวนการผลลัพธ์จะเหมือนกับการรัน

    GREP_OPTIONS='-v' grep one test.txt

    อย่างไรก็ตามคุณสามารถใช้สำนวนนี้หากคุณอยู่นอกทุบตีหรือไม่ต้องการที่จะเปิดเปลือกอื่น (ตัวอย่างเช่นเมื่อคุณใช้exec()ตระกูลของฟังก์ชั่นมากกว่าการsystem()โทร)

หมายเหตุเพิ่มเติมเกี่ยวกับ #!/usr/bin/env

และนี่ก็เป็นเหตุผลว่าทำไมสำนวนถูกนำมาใช้มากกว่า#!/usr/bin/env interpreter ไม่ต้องการพา ธ เต็มไปยังโปรแกรมเพราะมันใช้ฟังก์ชั่นที่ค้นหาตัวแปรเช่นเดียวกับที่เชลล์ทำและแทนที่ ตัวเองด้วยการรันคำสั่ง ดังนั้นจึงสามารถใช้เพื่อค้นหาตำแหน่งที่ล่าม (เช่น perl หรือ python) ที่ "อยู่" บนเส้นทาง#!/usr/bin/interpreterenvexecvp()PATH

นอกจากนี้ยังหมายความว่าโดยการปรับเปลี่ยนเส้นทางปัจจุบันคุณสามารถมีผลต่อตัวแปรหลามที่จะเรียกว่า สิ่งนี้ทำให้เป็นไปได้:

echo -e '#!/usr/bin/bash\n\necho I am an evil interpreter!' > python
chmod a+x ./python
export PATH=.
calibre

แทนที่จะเปิดตัว Caliber จะส่งผลให้

I am an evil interpreter!

ทำไม GREP_OPTIONS = '- v' grep one test.txt ทำงาน ฉันคิดว่ามันจำเป็นต้องใช้เครื่องหมายอัฒภาคหลังจาก '-v' (แต่ฉันลองแล้วมันใช้งานได้จริง)
Joe

2
เนื่องจากมีเครื่องหมายอัฒภาคจึงถูกตีความเป็นคำสั่ง bash สองคำสั่งแยกกัน คนแรกตั้งค่าตัวแปร (โดยไม่ส่งออก) และครั้งที่สองเริ่มต้นด้วยสภาพแวดล้อมที่ไม่มีตัวแปรส่งออก อย่างไรก็ตามหากไม่มีเซมิโคลอนนี่คือหนึ่งคำสั่ง (grep) นำหน้าด้วยการตั้งค่าสภาวะแวดล้อมโลคัล
มกราคม

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

1
@Pithikos ตัวแปรสภาพแวดล้อมถูกตั้งค่าโดย "การจัดหาสภาพแวดล้อม" โดยค่าเริ่มต้น bash จะส่ง bashrc ทั่วทั้งระบบ (หรือ profile.d หรือ bash_profile) จากนั้นจะเป็นแหล่งที่มาของผู้ใช้ของคุณ ~ / .bashrc (และ / หรือ ~ / .bash_profile) ไฟล์เหล่านี้อย่างใดอย่างหนึ่งสามารถมีคำสั่ง bash ไปยังสคริปต์อื่น ๆ ที่มาดังนั้นในที่สุดคุณสามารถมีตัวแปรสภาพแวดล้อมที่มาจากทั่วทุกสถานที่
Eric

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