อะไรคือความแตกต่างระหว่างการเรียกใช้ "bash script.sh" และ "./script.sh"


42

ถ้า script.sh เป็นอะไรที่เหมือน ๆ กัน

#!/bin/bash
echo "Hello World!"

มีวิธีที่ต้องการเรียกใช้สคริปต์หรือไม่ ฉันคิดว่าคุณต้อง chmod ก่อนดังนั้นมันจึงเป็นปฏิบัติการ?

คำตอบ:


56

สำหรับสคริปต์เฉพาะของคุณจะใช้งานได้ยกเว้นว่า./script.shต้องใช้บิตเรียกใช้และบิตที่อ่านได้ในขณะที่bash script.shต้องการเพียงบิตที่อ่านได้


สาเหตุของความแตกต่างของข้อกำหนดการอนุญาตขึ้นอยู่กับว่าโปรแกรมที่แปลสคริปต์ของคุณโหลดแล้ว:

  • ./script.sh ทำให้เชลล์ของคุณเรียกใช้ไฟล์ราวกับว่ามันเป็นปฏิบัติการปกติ

เชลล์แยกตัวเองและใช้การเรียกของระบบ (เช่นexecve) เพื่อให้ระบบปฏิบัติการเรียกใช้ไฟล์ในกระบวนการแยก ระบบปฏิบัติการจะตรวจสอบการอนุญาตของไฟล์ (ดังนั้นจำเป็นต้องตั้งค่าบิตการเรียกใช้งาน) และส่งต่อการร้องขอไปยังตัวโหลดโปรแกรมซึ่งดูที่ไฟล์และกำหนดวิธีดำเนินการ ในปฏิบัติการที่คอมไพล์ด้วย Linux เริ่มต้นด้วยหมายเลขมายากลของELFในขณะที่สคริปต์เริ่มต้นด้วย#!( hashbang ) ส่วนหัว hashbang หมายความว่าไฟล์เป็นสคริปต์และจำเป็นต้องตีความโดยโปรแกรมที่ระบุไว้หลังจาก hashbang สิ่งนี้อนุญาตให้สคริปต์บอกระบบถึงวิธีการตีความสคริปต์

ด้วยสคริปต์ของคุณตัวโหลดโปรแกรมจะดำเนินการ/bin/bashและส่งผ่าน./script.sh เป็นอาร์กิวเมนต์บรรทัดคำสั่ง

  • bash script.shทำให้เชลล์ของคุณทำงานbashและผ่านscript.shเป็นอาร์กิวเมนต์บรรทัดคำสั่ง

ดังนั้นระบบปฏิบัติการจะโหลดbash(ไม่ได้ดูscript.shเพราะมันเป็นเพียงอาร์กิวเมนต์บรรทัดคำสั่ง) bashกระบวนการที่สร้างขึ้นจะตีความว่าscript.shเพราะมันผ่านเป็นอาร์กิวเมนต์บรรทัดคำสั่ง เนื่องจากscript.shมีการอ่านโดยbashเป็นไฟล์ปกติเท่านั้นจึงไม่จำเป็นต้องใช้บิตการทำงาน


ฉันแนะนำให้ใช้./script.shเนื่องจากคุณอาจไม่ทราบว่าต้องใช้ตัวแปลภาษาใด ดังนั้นให้โหลดโปรแกรมกำหนดว่าสำหรับคุณ


3
หากไม่ได้ตั้งค่าบิตที่เรียกใช้งานได้คุณสามารถเรียกใช้สคริปต์ได้โดยทำ ". ./script.sh"
Dog eat cat world

1
@Dog คุณถูกต้อง จุดเป็นทางลัดสำหรับคำสั่งในตัว 'แหล่งที่มา' ซึ่งเรียกใช้สคริปต์ในกระบวนการทุบตีปัจจุบัน ดังนั้นจำเป็นต้องใช้บิตที่อ่านได้เท่านั้น
SkyDan

5
@Dogeatcatworld ในขณะที่เป็นจริงการทำงาน. ./script.shไม่เหมือนกับbash script.sh(หรือ./script.shพิจารณาสคริปต์#!/usr/bin/python -V<newline> print test.
casey

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

6
โปรดทราบว่าหากคุณแหล่งสคริปต์ในไดเรกทอรีปัจจุบันคุณไม่จำเป็นต้องใช้. / ; . script.shเพียงแค่พูดว่า แต่ฉันเห็นด้วยกับคนที่ไม่สนับสนุนการใช้.คำสั่งในสคริปต์ที่ไม่ได้ตั้งใจจะเรียกใช้เช่นนั้น ฉันประหลาดใจที่ไม่มีใครพูดถึงว่าถ้าสคริปต์มีexitคำสั่งและคุณก็มามันก็อาจจะนำคุณออกจากระบบ ปัญหาที่น่ากลัวน้อยกว่าคือถ้าสคริปต์ทำcdเช่นนั้นจะส่งผลกระทบต่อเชลล์หลัก (แบบโต้ตอบ)
สกอตต์

18

bash script.shเรียกใช้สคริปต์โดยตรงโดยใช้ bash
./script.shกำลังใช้ shebang #!/bin/bashเพื่อกำหนดวิธีดำเนินการ

ถ้าคุณอยากรู้จริง ๆ ว่าไบนารีตัวไหนถูกเรียกใช้ถ้าคุณทำbash script.shคุณสามารถหาคำตอบwhich bashได้

ดังนั้นในตัวอย่างของคุณมันไม่ได้สร้างความแตกต่าง ใช่คุณต้องเพื่อให้สามารถดำเนินการได้โดยตรงผ่านทางchmod +x script.sh./script.sh


2
ดีก็ทำให้ไม่แตกต่างสมมติว่า/bin/bashเป็นครั้งแรกในของคุณbash $PATH
cjm

คุณถูก. และ shebang #!/bin/bashเป็นเพียงการทำงานถ้ามี/bin/bash
xx4h

Bash (เวอร์ชั่น 4.2.37) ในระบบของฉันเรียกใช้งานสคริปต์แม้ไม่มีการตั้งค่าบิตการเรียกใช้งาน ทำไมคุณถึงบอกว่าจำเป็นต้องมีบิตการประมวลผล
SkyDan

./script.shใช่บิตการดำเนินการเป็นสิ่งจำเป็นโดยเรียกผ่านเท่านั้น
xx4h

4

สร้างไฟล์ Delete_Self.sh เช่นนี้:

 #!/bin/rm

 echo I am still here!

เรียกใช้สคริปต์นี้ตามที่sh Delete_Self.shคุณจะเห็น "ฉันยังอยู่ที่นี่!" สะท้อนกลับมา

ทำให้สามารถเรียกใช้งานได้และรันตามที่./Delete_Self.shคุณจะไม่เห็นสิ่งใดสะท้อนกลับในขณะที่ไฟล์Delete_Self.shนั้นหายไป

ดังนั้นความแตกต่างคือ:

  • bash script.shจะเพิกเฉย #! บรรทัดเนื่องจากมีการระบุ bash เป็นโปรแกรมเพื่อรัน script.sh
  • ./script.shจะอ่าน #! script.shสายการกำหนดโปรแกรมทำงาน

+1 สำหรับตัวอย่างที่ดี
ThisaruG

1

นอกเหนือจากคำตอบอื่น ๆ แล้วการรู้ถึงความแตกต่างระหว่างการเรียกใช้สคริปต์ผ่าน./script.sh(i) และแหล่งที่มา./script.sh(ii) นั้นมีประโยชน์ - รุ่น (i) จะสร้างเชลล์ใหม่ที่จะเรียกใช้คำสั่งในขณะที่ (ii) เรียกใช้คำสั่ง เปลือกปัจจุบัน - ซึ่งสามารถบังคับถ้าปฏิบัติการเปลี่ยนแปลงตัวแปรสภาพแวดล้อมที่จำเป็นต้องเก็บรักษาไว้หลังจากออกจากปฏิบัติการ ตัวอย่างเช่นในการเปิดใช้งานสภาพแวดล้อมแบบหลามต้องใช้สิ่งต่อไปนี้:

source activate my_env

NB ทางเลือกอื่นsourceที่คุณอาจพบคือใน.ตัวเช่น

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