อะไรคือข้อแตกต่างระหว่างการเรียกใช้งานสคริปต์ Bash เช่น A และการจัดหาสคริปต์ Bash เช่น B
A
> ./myscript
B
> source myscript
อะไรคือข้อแตกต่างระหว่างการเรียกใช้งานสคริปต์ Bash เช่น A และการจัดหาสคริปต์ Bash เช่น B
A
> ./myscript
B
> source myscript
คำตอบ:
การจัดหาสคริปต์จะเรียกใช้คำสั่งในกระบวนการเชลล์ปัจจุบัน
การเรียกใช้สคริปต์จะเรียกใช้คำสั่งในกระบวนการเชลล์ใหม่
ใช้ซอร์สหากคุณต้องการให้สคริปต์เปลี่ยนสภาวะแวดล้อมในเชลล์ที่รันอยู่ในปัจจุบัน ใช้รันเป็นอย่างอื่น
หากคุณยังสับสนอยู่โปรดอ่านต่อ
ในการชี้แจงความสับสนทั่วไปเกี่ยวกับไวยากรณ์ที่จะดำเนินการและไวยากรณ์ของแหล่งที่มา:
./myscript
สิ่งนี้จะดำเนินการ myscript
โดยมีเงื่อนไขว่าไฟล์ดังกล่าวสามารถเรียกใช้งานได้และอยู่ในไดเรกทอรีปัจจุบัน จุดนำและเครื่องหมายทับ ( ./
) แสดงถึงไดเรกทอรีปัจจุบัน สิ่งนี้จำเป็นเนื่องจากไดเรกทอรีปัจจุบันมักจะไม่ (และโดยปกติไม่ควร) $PATH
มา
myscript
ซึ่งจะดำเนินการ ถ้าไฟล์เป็นปฏิบัติการและอยู่ในไดเรกทอรีในบางmyscript
$PATH
source myscript
นี้จะมา myscript
ไฟล์ไม่จำเป็นต้องสามารถเรียกใช้งานได้ แต่จะต้องเป็นเชลล์สคริปต์ที่ถูกต้อง $PATH
ไฟล์ที่สามารถอยู่ในไดเรกทอรีปัจจุบันหรือในไดเรกทอรีใน
. myscript
นี้จะยังแหล่งที่มา myscript
นี้ "สะกด" อย่างเป็นทางการอย่างใดอย่างหนึ่งตามที่กำหนดโดยPOSIX ทุบตีกำหนดsource
เป็นนามแฝงของจุด
พิจารณาmyscript.sh
เนื้อหาต่อไปนี้:
#!/bin/sh
# demonstrate setting a variable
echo "foo: "$(env | grep FOO)
export FOO=foo
echo "foo: "$(env | grep FOO)
# demonstrate changing of working directory
echo "PWD: "$PWD
cd somedir
echo "PWD: "$PWD
ก่อนที่เราจะรันสคริปต์ก่อนอื่นเราจะตรวจสอบสภาพแวดล้อมปัจจุบัน:
$ env | grep FOO
$ echo $PWD
/home/lesmana
FOO
ไม่ได้กำหนดตัวแปรและเราอยู่ในโฮมไดเรกทอรี
ตอนนี้เรารันไฟล์:
$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
ตรวจสอบสภาพแวดล้อมอีกครั้ง:
$ env | grep FOO
$ echo $PWD
/home/lesmana
FOO
ไม่ได้ตั้งค่าตัวแปรและไดเรกทอรีการทำงานไม่เปลี่ยนแปลง
เอาต์พุตสคริปต์แสดงอย่างชัดเจนว่าตัวแปรถูกตั้งค่าและไดเร็กทอรีถูกเปลี่ยน การตรวจสอบหลังจากนั้นแสดงว่าตัวแปรไม่ได้ถูกตั้งค่าและไม่มีการเปลี่ยนแปลงไดเรกทอรี เกิดอะไรขึ้น? การเปลี่ยนแปลงที่ถูกสร้างขึ้นมาในใหม่เปลือก ปัจจุบันเปลือกกลับกลายเป็นใหม่เปลือกเพื่อเรียกใช้สคริปต์ สคริปต์กำลังทำงานในเชลล์ใหม่และการเปลี่ยนแปลงทั้งหมดในสภาพแวดล้อมมีผลในเชลล์ใหม่ หลังจากสคริปต์เสร็จสิ้นเชลล์ใหม่จะถูกทำลาย การเปลี่ยนแปลงสภาพแวดล้อมในเชลล์ใหม่ทั้งหมดจะถูกทำลายด้วยเชลล์ใหม่ ข้อความเอาต์พุตเท่านั้นที่จะพิมพ์ในเชลล์ปัจจุบัน
ตอนนี้เรามาไฟล์:
$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
ตรวจสอบสภาพแวดล้อมอีกครั้ง:
$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir
ตัวแปร FOO ถูกตั้งค่าและไดเรกทอรีการทำงานมีการเปลี่ยนแปลง
การจัดหาสคริปต์ไม่ได้สร้างเชลล์ใหม่ คำสั่งทั้งหมดจะทำงานในเชลล์ปัจจุบันและการเปลี่ยนแปลงสภาพแวดล้อมจะมีผลในเชลล์ปัจจุบัน
โปรดทราบว่าในตัวอย่างง่ายๆนี้ผลลัพธ์ของการดำเนินการจะเหมือนกับการจัดหาสคริปต์ กรณีนี้ไม่จำเป็นเสมอไป
พิจารณาสคริปต์ต่อไปนี้pid.sh
:
#!/bin/sh
echo $$
(ตัวแปรพิเศษ$$
ขยายเป็น PID ของกระบวนการเชลล์ปัจจุบัน)
พิมพ์ PID ของเชลล์ปัจจุบันก่อน:
$ echo $$
25009
ส่งสคริปต์:
$ source pid.sh
25009
ดำเนินการสคริปต์บันทึก PID:
$ ./pid.sh
25011
แหล่งที่มาอีกครั้ง:
$ source pid.sh
25009
ดำเนินการอีกครั้ง:
$ ./pid.sh
25013
คุณจะเห็นว่าการจัดหาสคริปต์ทำงานในกระบวนการเดียวกันในขณะที่ดำเนินการสคริปต์จะสร้างกระบวนการใหม่ทุกครั้ง กระบวนการใหม่นั้นคือเชลล์ใหม่ที่สร้างขึ้นสำหรับการดำเนินการของสคริปต์ การจัดหาสคริปต์ไม่ได้สร้างเชลล์ใหม่ดังนั้น PID จึงยังคงเหมือนเดิม
ทั้งการจัดหาและการดำเนินการสคริปต์จะเรียกใช้คำสั่งในสคริปต์บรรทัดต่อบรรทัดราวกับว่าคุณพิมพ์คำสั่งเหล่านั้นด้วยมือทีละบรรทัด
ความแตกต่างคือ:
ใช้ซอร์สหากคุณต้องการให้สคริปต์เปลี่ยนสภาวะแวดล้อมในเชลล์ที่รันอยู่ในปัจจุบัน ใช้รันเป็นอย่างอื่น
ดูสิ่งนี้ด้วย:
source myscript.sh
และ. myscript.sh
?
การเรียกใช้งานสคริปต์จะดำเนินการในกระบวนการลูกที่แยกต่างหากกล่าวคือมีการเรียกใช้อินสแตนซ์เชลล์แยกต่างหากเพื่อประมวลผลสคริปต์ ซึ่งหมายความว่าตัวแปรสภาพแวดล้อมอื่น ๆ ที่กำหนดไว้ในสคริปต์ไม่สามารถอัปเดตในเชลล์พาเรนต์ (ปัจจุบัน)
การจัดหาสคริปต์หมายความว่ามีการแยกวิเคราะห์และดำเนินการโดยเชลล์ปัจจุบันเอง มันเหมือนกับว่าคุณพิมพ์เนื้อหาของสคริปต์ ด้วยเหตุนี้สคริปต์ที่มีการจัดหาจึงไม่จำเป็นต้องถูกเรียกใช้งาน แต่มันจะต้องสามารถเรียกใช้งานได้หากคุณกำลังเรียกใช้งานแน่นอน
หากคุณมีข้อโต้แย้งตำแหน่งในเปลือกปัจจุบันพวกเขาจะไม่เปลี่ยนแปลง
ดังนั้นถ้าฉันมีไฟล์a.sh
ที่มี:
echo a $*
และฉันทำ:
$ set `date`
$ source ./a.sh
ฉันชอบ:
a Fri Dec 11 07:34:17 PST 2009
โดย:
$ set `date`
$ ./a.sh
ให้ฉัน:
a
หวังว่าจะช่วย
การจัดหาเป็นหลักเหมือนกับการพิมพ์แต่ละบรรทัดของสคริปต์ในที่พร้อมรับคำสั่งทีละครั้ง ...
การดำเนินการเริ่มต้นกระบวนการใหม่แล้วเรียกใช้แต่ละบรรทัดของสคริปต์เพียงปรับเปลี่ยนสภาพแวดล้อมปัจจุบันโดยสิ่งที่มันกลับมา
นอกเหนือจากข้างต้นการเรียกใช้สคริปต์ตามที่./myscript
กำหนดให้ต้องมีการอนุญาตให้ใช้งานสำหรับไฟล์ myscript ในขณะที่การจัดหาไม่จำเป็นต้องมีการอนุญาตให้เรียกใช้งาน นั่นคือเหตุผลที่chmod +x myscript
ไม่จำเป็นก่อนsource myscript
bash myscript
แต่ถ้าเป็นปัญหาที่คุณสามารถเรียกใช้
การจัดหาคุณจะได้รับตัวแปรพิเศษทั้งหมดที่กำหนดไว้ในสคริปต์
ดังนั้นหากคุณมีการกำหนดค่าหรือคำจำกัดความของฟังก์ชั่นคุณควรเลือกแหล่งที่มาและไม่ดำเนินการ การประหารชีวิตนั้นไม่ขึ้นอยู่กับสภาพแวดล้อมของผู้ปกครอง
หากฉันจำได้ถูกต้องการเรียกใช้สคริปต์จะเรียกใช้ไฟล์ปฏิบัติการใน#!
บรรทัดที่มีไฟล์สคริปต์เป็นอาร์กิวเมนต์ (โดยทั่วไปจะเริ่มเชลล์ใหม่และการจัดหาสคริปต์ในเชลล์ใหม่ได้อย่างมีประสิทธิภาพเช่นเดียวกับ#!/bin/sh
);
ในขณะที่การจัดหาสคริปต์จะดำเนินการแต่ละบรรทัดในสภาพแวดล้อมเชลล์ปัจจุบันของคุณซึ่งมีประโยชน์ในการกลายพันธุ์เชลล์ปัจจุบันของคุณ (ตัวอย่างเช่นให้วิธีกำหนดฟังก์ชันเชลล์และตัวแปรสภาพแวดล้อมการส่งออก)
source
คำสั่งรันสคริปต์ที่จัดเตรียมไว้(สิทธิ์ในการเรียกใช้งานนั้นไม่บังคับ )ในสภาพแวดล้อมเชลล์ปัจจุบันในขณะที่./
เรียกใช้งานสคริปต์ปฏิบัติการที่จัดเตรียมไว้ให้ในเชลล์ใหม่
ตรวจสอบคำตอบนี้เช่น: https://superuser.com/a/894748/432100