ทำไมคุณต้องใส่ #! / bin / bash ที่จุดเริ่มต้นของไฟล์สคริปต์


486

ฉันเคยสร้างสคริปต์Bashมาก่อนและพวกเขาก็ทำงานได้ดีโดยไม่ต้อง#!/bin/bashเริ่มต้น

จุดประสงค์ของการวางไว้คืออะไร? สิ่งต่าง ๆ จะแตกต่างกันอย่างไร

นอกจากนี้คุณออกเสียง#อย่างไร ฉันรู้ว่า!มันออกเสียงว่า "ปัง"

#!เด่นชัดเป็นอย่างไร


8
คุณไม่จำเป็นต้องทำและไม่ควรทำถ้าคุณไม่มีทางเลือก ใช้ '#! / bin / sh' ในขณะที่คุณสามารถและเรียนรู้เกี่ยวกับความแตกต่างระหว่างเชลล์ (POSIX) และ bash จะมีวันหนึ่งก่อนที่เรซูเม่ของคุณจะเติบโตนานเกินไปเมื่อคุณจะพบว่าตัวเองอยู่ในระบบที่มีเชลล์แตกต่างกันและคุณยังต้องการให้สคริปต์ทำงาน
Jens

50
มันออกเสียงว่า "Hash-Bang" หรือ "She-Bang"
Beachhouse

22
ฉันคิดว่ามันคุ้มค่าที่จะทราบว่านี่จะถูกดำเนินการก็ต่อเมื่อคุณเรียกใช้สคริปต์ของคุณในฐานะที่ปฏิบัติการได้ ดังนั้นหากคุณตั้งค่าสถานะที่ปฏิบัติการได้จากนั้นให้พิมพ์./yourscript.extensionเช่น./helloworld.pyหรือ./helloworld.shจะค้นหาล่ามที่บรรทัดบนสุดซึ่งจะเป็น#!/bin/pythonหรือ!#/bin/bashในขณะที่ดำเนินการสคริปต์เช่นpython helloworld.pyบรรทัดแรกจะไม่ถูกสังเกตเพราะถูกใส่ความคิดเห็น ออก. ดังนั้นมันจึงเป็นลำดับพิเศษสำหรับเชลล์ / เคอร์เนล
JFA

@JFA มีการเปลี่ยนแปลงลำดับระหว่าง bash และ python เมื่อใช้! # สำหรับ python และ #! เพื่อทุบตี?
AAI

1
@Ajeya ไม่เป็นรูปแบบที่ผิดพลาดจับได้ดี
JFA

คำตอบ:


426

มันเป็นแบบแผนดังนั้นเชลล์ * nix จึงรู้ว่าล่ามชนิดใดที่จะเรียกใช้

ตัวอย่างเช่นรสชาติเก่าของ ATT เริ่มต้นเป็นsh (เชลล์เป้าหมาย) ในขณะที่เวอร์ชันเก่าของ BSD เริ่มต้นเป็นcsh (เชลล์ C)

แม้กระทั่งวันนี้ (ที่ระบบส่วนใหญ่ทำงานทุบตีที่"Bourne Again Shell" ) สคริปต์สามารถในการทุบตีหลาม, Perl, ทับทิม, PHP, ฯลฯ ฯลฯ ตัวอย่างเช่นคุณอาจเห็นหรือ#!/bin/perl#!/bin/perl5

PS: เครื่องหมายอัศเจรีย์ ( !) เรียกว่าเสน่หา"ปัง" เปลือกคิดเห็นสัญลักษณ์ ( #) บางครั้งเรียกว่า"กัญชา"

PPS: จำ - ใต้ระวัง * เชื่อมโยงต่อท้ายด้วยประเภทไฟล์เป็นเพียงการประชุมไม่ได้เป็น"กฎ" ปฏิบัติการสามารถเป็นโปรแกรมไบนารีหนึ่งในล้านประเภทสคริปต์และสิ่งอื่น ๆ ได้เป็นอย่างดีใด ๆ #!/bin/bashดังนั้นความจำเป็นในการ


1
ฉันพบข้อมูลเกี่ยวกับสิ่งอื่นที่มีประโยชน์แล้ว $ # เรียกว่าอะไร
โหนดนินจา

91
shebang ไม่ใช่แบบแผนของเชลล์มันถูกตีความโดยเคอร์เนลเมื่อจัดการexecve(2)syscall; ดังนั้น shebang จึงเป็นแบบแผนเคอร์เนลไม่ใช่แบบเชลล์
Basile Starynkevitch

10
นอกจากนี้ยังช่วยให้ผู้แก้ไขบางรายเช่น Vim กำหนดภาษาสำหรับการเน้นไวยากรณ์หากไฟล์ไม่มีส่วนขยาย หากไม่มี Shebang แล้ว Vim จะแสดงสคริปต์ทุบตีเหมือนกับไฟล์ข้อความธรรมดา
Aaron Blenkush

1
มันทำให้ฉันสงสัยว่าคุณจะต้องเพิ่ม#!/bin/shสิ่งที่ต้องการ.profileและสิ่งที่วิ่งonload
Kolob แคนยอน

5
ดังนั้น ... hash-bang-slash-bin-slash-bash ?
Bernat

134

เพื่อให้แม่นยำยิ่งขึ้นshebang #!เมื่อไฟล์นี้เป็นสองไบต์แรกของไฟล์เรียกทำงาน ( x โหมด ) จะถูกตีความโดยการเรียกระบบexecve (2) (ซึ่งเรียกใช้งานโปรแกรม) แต่ข้อมูลจำเพาะ POSIXexecveไม่ต้องพูดถึง shebang

มันจะต้องตามด้วยเส้นทางไฟล์ของล่ามที่ปฏิบัติการได้ (ซึ่ง BTW อาจเป็นญาติได้ แต่ส่วนใหญ่มักจะเป็นแบบสัมบูรณ์)

กลลวงที่ดี (หรืออาจจะไม่ค่อยดีนัก ) ในการค้นหาล่าม (เช่นpython) ในผู้ใช้$PATHคือการใช้envโปรแกรม ( /usr/bin/envบน Linux ทุกตัวเสมอ) เช่น

 #!/usr/bin/env python

ปฏิบัติการใด ๆ ของ ELF สามารถเป็นล่ามได้ คุณสามารถใช้#!/bin/catหรือ#!/bin/trueถ้าคุณต้องการ! (แต่นั่นก็มักจะไร้ประโยชน์)


8
ดูคำถามนี้สำหรับการสนทนาของ#!/usr/bin/envแฮ็ค
Keith Thompson

#!/usr/bin/env bash -xถ้าผมต้องการที่จะผ่านอาร์กิวเมนต์หลามฉันจะทำอย่างนั้นจริงฉันต้องการที่จะดำเนินการ ฉันจะทำอย่างไร
indianwebdevil

มันง่ายฉันพบว่าตัวเองเพียงแค่เพิ่มพารามิเตอร์หลังจากนั้น#!/usr/bin/env bash -x
indianwebdevil

bashเกือบตลอดเวลา/bin/bashดังนั้น shebang ของคุณควรจะเป็น#!/bin/bash -x
Basile Starynkevitch

49

มันเรียกว่าshebang ในยูนิกซ์ - พูด, # เรียกว่าคมชัด (เหมือนในเพลง) หรือแฮช (เช่นแฮชแท็กบน Twitter) และ! เรียกว่าปัง (คุณสามารถอ้างอิงคำสั่งเชลล์ก่อนหน้าของคุณด้วย !!, เรียกว่า bang-bang) ดังนั้นเมื่อรวมกันคุณจะได้รับ haSH-BANG หรือ shebang

ส่วนหลัง #! บอก Unix ว่าจะใช้โปรแกรมใดในการรัน หากไม่ได้ระบุไว้จะลองใช้ bash (หรือ sh หรือ zsh หรือตัวแปร $ SHELL ของคุณ) แต่ถ้ามีก็จะใช้โปรแกรมนั้น นอกจากนี้ # คือความคิดเห็นในภาษาส่วนใหญ่ดังนั้นสายจะถูกละเว้นในการดำเนินการที่ตามมา


2
หากฉันอยู่ใน bash แล้วจะเริ่มต้นอินสแตนซ์ bash อีกครั้งหรือไม่หากเห็น #! / bin / bash เกิดอะไรขึ้นถ้าฉันทุบตีแล้วปล่อยทิ้งไว้? มีความแตกต่างหรือไม่?
โหนดนินจา

2
@javascriptninja ไม่ว่าจะเป็นวิธีใดก็จะเริ่มเชลล์ bash ใหม่ ในกรณีของการทุบตีมีความแตกต่างไม่จริง ๆ ตราบใดที่คุณกำลังใช้ทุบตีอยู่แล้ว Shebang มีความสำคัญถ้า (a) คุณจำเป็นต้องเรียกใช้ในสิ่งที่ไม่ใช่แค่เปลือกหอยเช่น python หรือ perl หรือ (b) คุณไม่ใช้ bash shell (เช่นคุณใช้ zsh) แต่คุณต้อง เรียกใช้บางสิ่งบางอย่างที่ต้องมีการทำงานในทุบตี
austin1howard

อย่างไรก็ตามในความคิดของฉันมันเป็นวิธีปฏิบัติที่ดีในการใส่ Shebang ดังนั้นบางคนที่อ่านรหัสก็รู้ว่าเกิดอะไรขึ้น
austin1howard

2
ผิด: execve(2)syscall ไม่ใช้$SHELLตัวแปร มันเป็นเคอร์เนลที่แปลความหมายของ Shebang
Basile Starynkevitch

1
@BasileStarynkevitch ที่ถูกต้องตัวโหลด elf ในเคอร์เนลตีความ shebang ฉันระบุว่าจะใช้ $ SHELL หากไม่มี Shebang ให้
austin1howard

19

shebangเป็นคำสั่งที่จะโหลดที่จะใช้โปรแกรมที่มีการระบุหลังจากที่#!เป็นล่ามสำหรับไฟล์ในคำถามเมื่อคุณพยายามที่จะดำเนินการได้ ดังนั้นถ้าคุณพยายามที่จะเรียกใช้ไฟล์ที่เรียกว่าfoo.shซึ่งมีที่ด้านบนคำสั่งที่เกิดขึ้นจริงที่วิ่งเป็น#!/bin/bash /bin/bash foo.shนี่เป็นวิธีที่ยืดหยุ่นในการใช้ล่ามที่แตกต่างกันสำหรับโปรแกรมต่างๆ นี่คือสิ่งที่นำมาใช้ในระดับระบบและ API ระดับผู้ใช้เป็นแบบแผน shebang

นอกจากนี้ยังควรรู้ด้วยว่า shebang เป็นหมายเลขอาถรรพ์ - มนุษย์ที่สามารถอ่านได้ซึ่งระบุว่าไฟล์เป็นสคริปต์สำหรับล่ามที่ให้ไว้

ประเด็นของคุณเกี่ยวกับเรื่องนี้ "ทำงาน" แม้ไม่มี shebang เป็นเพียงเพราะโปรแกรมที่เป็นปัญหาคือเชลล์สคริปต์ที่เขียนขึ้นสำหรับเชลล์เดียวกับที่คุณใช้ ตัวอย่างเช่นคุณสามารถเขียนไฟล์ javascript ได้ดีจากนั้นให้ใส่#! /usr/bin/js(หรือสิ่งที่คล้ายกัน) เพื่อให้มีสคริปต์ "เชลล์สคริปต์" จาวาสคริปต์


18

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


15

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

ทุบตีมีการพัฒนาในช่วงหลายปีที่เกิดจากรหัสและkshsh

การเพิ่ม#!/bin/bashเป็นบรรทัดแรกของสคริปต์ของคุณบอกให้ระบบปฏิบัติการเรียกใช้งานที่ระบุshellเพื่อดำเนินการคำสั่งที่ตามมาในสคริปต์

#! มักเรียกว่า "hash-bang", "she-bang" หรือ "sha-bang"


9

มันถูกเรียกว่าshebang ประกอบด้วยเครื่องหมายตัวเลขและอักขระเครื่องหมายอัศเจรีย์ (#!) ตามด้วยเส้นทางแบบเต็มไปยังล่ามเช่น / bin / bash สคริปต์ทั้งหมดภายใต้ UNIX และ Linux ดำเนินการโดยใช้ล่ามที่ระบุในบรรทัดแรก


1

นอกจากนี้คุณจะเห็นพารามิเตอร์อื่น ๆ หลังจาก #! / bin / bash เช่น
#!/bin/bash -v -x
อ่านสิ่งนี้เพื่อรับแนวคิดเพิ่มเติม /unix/124272/what-do-the-arguments-v-and-x-mean-to-bash


0

มันจะเป็นประโยชน์กับคนที่ใช้ระบบที่แตกต่างกันที่ไม่ได้มีห้องสมุดที่พร้อมใช้งาน หากไม่ได้รับการประกาศและคุณมีฟังก์ชั่นบางอย่างในสคริปต์ของคุณที่ไม่ได้รับการสนับสนุนโดยระบบนั้นคุณควรประกาศ # / bin / bash ฉันพบปัญหานี้ก่อนที่จะทำงานและตอนนี้ฉันเพิ่งรวมไว้เป็นแบบฝึกหัด

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