Bash shebang ที่ต้องการคืออะไร


1131

มีBashshebang ใดที่มีความหมายดีกว่าคนอื่น ๆ สำหรับการใช้งานส่วนใหญ่หรือไม่?

  • #!/usr/bin/env bash
  • #!/bin/bash
  • #!/bin/sh
  • #!/bin/sh -
  • ฯลฯ

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


4
และ/usr/local/bin/bashใน OpenBSD
jww

คำตอบ:


1535

คุณควรใช้#!/usr/bin/env bashสำหรับพกพา : nixes * ที่แตกต่างกันใส่bashในสถานที่ที่แตกต่างกันและการใช้/usr/bin/envเป็นวิธีแก้ปัญหาในการทำงานครั้งแรกที่พบในbash PATHและไม่ได้เป็นshbash


9
ขอบคุณ นอกจากนี้ดูเหมือนว่าการเพิ่ม - ไปที่ส่วนท้ายของ $! / usr / bin / env bash - จะไม่ทำอะไรเลยเนื่องจากมีเพียงอาร์กิวเมนต์เดียวที่อนุญาตโดย * nix ใน shebang และนั่นใช้ 'bash' เห็นได้ชัดว่ามีประโยชน์สำหรับการป้องกันข้อโต้แย้งที่เป็นอันตรายที่ถูกส่งผ่านไปยังสคริปต์ใน commandline หาก Shebang ของสคริปต์เป็นหนึ่งในรายการอื่นที่ไม่มีข้อโต้แย้ง ( /bin/shฯลฯ )
Kurtosis

13
@ เรย์bashไม่ได้อยู่ใน/binทุกระบบ
ptierno

12
เหมือนกันสำหรับฉันฉันเพิ่งเพิ่มไปยังนามแฝง: alias shebang='echo "#!/usr/bin/env bash"'ตอนนี้ฉันแค่ต้องเปิด terminal และพิมพ์ shebang แทนที่จะไปที่นี่
Oylex

19
คำตอบนี้เป็นการหลอกลวง POSIX ไม่ได้บอกว่าเป็นที่env /usr/bin/envมันอาจจะเป็นที่/bin/envใดก็ได้ในความเป็นจริงตราบใดที่มันอยู่ในเส้นทาง มันอาจจะเป็นที่/dummy/envถ้าอยู่ใน/dummy PATHShebang นั้นไม่ได้กำหนดภายใต้ POSIX ดังนั้นฉันสามารถ#!stop toasterเริ่มต้นเครื่องชงกาแฟแบบ USB และเข้ากันได้กับ POSIX ดังนั้น#!/usr/bin/env bashมันจึงไม่ได้ดีกว่า#!/bin/bashมันสามารถพกพาได้น้อยลง
darkfeline

19
@darkfeline Portability ไม่สมบูรณ์ - เป็นไปไม่ได้ทางคณิตศาสตร์ที่จะสร้างสคริปต์ใด ๆ ที่จะทำสิ่งเดียวกันในทุกแพลตฟอร์ม ตั้งแต่ปี 2012 ถึงปี 2018 /usr/bin/envมีอยู่ในเครื่องมากกว่า/bin/bashxor ตัวใดตัวหนึ่ง/usr/bin/bashดังนั้นสคริปต์ที่ขึ้นต้นด้วยบรรทัดนี้จะทำสิ่งที่คาดหวังบนเครื่องให้ได้มากที่สุด
l0b0

80

/bin/shมักจะมีการเชื่อมโยงไปยังเปลือกของระบบเริ่มต้นซึ่งมักจะเป็นbashแต่ในเช่นระบบ Debian dashเป็นน้ำหนักเบา ไม่ว่าจะด้วยวิธีใดเชลล์ Bourne ดั้งเดิมคือshดังนั้นหากสคริปต์ของคุณใช้คุณสมบัติเฉพาะบางประการbash(รุ่นที่ 2, "Bourne Again sh") ( [[ ]]การทดสอบอาร์เรย์สิ่งต่าง ๆ ที่หวาน ฯลฯ ) คุณควรจะเจาะจงมากขึ้นและใช้ในภายหลัง . วิธีนี้ในระบบที่ไม่ได้ติดตั้ง bash สคริปต์ของคุณจะไม่ทำงาน ฉันเข้าใจว่าอาจมีไตรภาคที่น่าตื่นเต้นของภาพยนตร์เกี่ยวกับวิวัฒนาการนี้ ... แต่นั่นอาจเป็นข่าวลือ

นอกจากนี้ยังทราบว่าเมื่อปรากฏเป็นsh, bashมีขอบเขตพฤติกรรมเป็นมาตรฐาน POSIX sh (ดูเอกสาร GNUเกี่ยวกับเรื่องนี้)


2
Public Domain Korn Shell (pdksh) เป็นค่าเริ่มต้นใน OpenBSD
jww

ระบบส่วนใหญ่จะไม่เชื่อมโยง/bin/shกับที่ใด ๆ/usrเนื่องจากจะทำให้ค่อนข้างยากสำหรับสคริปต์เริ่มทำงานก่อนที่/usrจะติดตั้ง
aij

@aij ฉันไม่ทราบว่าทำไมฉันจึงใส่ "มากหรือมากที่สุด" ที่นั่น - ฉันเป็นผู้ใช้ fedora ที่/binและ/sbinเป็นเวลาหลายปีที่มีการเชื่อมโยงโดยค่าเริ่มต้นไปยัง/usr/binและ/usr/sbinดังนั้นในบริบท/bin/shนั้นเป็นลิงก์bashและของจริง /usr/binไดเรกทอรี แต่ฉันจะแก้ไขให้ถูกต้อง
ละเอียดอ่อน

44

ฉันแนะนำให้ใช้:

#!/bin/bash

ไม่ใช่แบบพกพา 100% (บางระบบวางbashในตำแหน่งอื่นที่ไม่ใช่/bin) แต่ความจริงที่ว่าสคริปต์ที่มีอยู่จำนวนมากใช้#!/bin/bashแรงกดดันระบบปฏิบัติการต่าง ๆ เพื่อสร้าง/bin/bashsymlink ให้กับตำแหน่งหลักอย่างน้อย

ทางเลือกของ:

#!/usr/bin/env bash

ได้รับการแนะนำ - แต่ไม่รับประกันว่าenvคำสั่งนั้นจะอยู่ใน/usr/bin(และฉันได้ใช้ระบบที่ไม่เป็น) นอกจากนี้แบบฟอร์มนี้จะใช้อินสแตนซ์แรกของbashผู้ใช้ปัจจุบัน$PATHซึ่งอาจไม่ใช่เวอร์ชันที่เหมาะสมของ bash shell

(แต่/usr/bin/envควรทำงานกับระบบที่ทันสมัยพอสมควรไม่ว่าenvจะเป็นเพราะอะไร/usr/binหรือเป็นเพราะระบบทำบางสิ่งบางอย่างเพื่อให้มันทำงานได้ระบบที่ฉันอ้างถึงข้างต้นคือ SunOS 4 ซึ่งฉันอาจไม่ได้ใช้ในเวลาประมาณ 25 ปี)

หากคุณต้องการให้สคริปต์ทำงานบนระบบที่ไม่มี/bin/bashคุณสามารถแก้ไขสคริปต์ให้ชี้ไปยังตำแหน่งที่ถูกต้อง (ซึ่งไม่สะดวกเป็นที่ยอมรับ)

ผมได้กล่าวถึงความสมดุลในเชิงลึกมากขึ้นในคำตอบของฉันไปที่คำถามนี้

การปรับปรุงที่ค่อนข้างคลุมเครือ: หนึ่งในระบบการใช้งานผมTermux , สก์ท็อปลินุกซ์เหมือนชั้นที่ทำงานภายใต้ Android ไม่ได้มี/bin/bash( bashเป็น/data/data/com.termux/files/usr/bin/bash) - #!/bin/bashแต่มันก็มีการจัดการพิเศษที่ให้การสนับสนุน


3
2 ปีต่อมาและนี่คือคำแนะนำที่ดีที่สุดที่นี่ หากวิธีการแก้ปัญหาอย่างง่ายไม่ทำงานคุณต้องถามคำถามก่อนตัดสินใจ คำตอบที่ได้รับการยอมรับและได้รับการโหวตมากที่สุดนั้นไม่ผิดมันไม่ถูกต้อง :)
Software Engineer

27

การใช้สาย shebang เพื่อเรียกใช้ล่ามที่เหมาะสมนั้นไม่ได้มีไว้สำหรับ BASH เท่านั้น คุณสามารถใช้ shebang สำหรับภาษาที่ตีความใด ๆ ในระบบของคุณเช่น Perl, Python, PHP (CLI) และอื่น ๆ อีกมากมาย โดยวิธีการที่ Shebang

#!/bin/sh -

(อาจเป็นสองขีดกลางได้เช่นกัน--) สิ้นสุดตัวเลือก bash ทุกอย่างหลังจากนั้นจะถือว่าเป็นชื่อไฟล์และอาร์กิวเมนต์

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

#!/usr/bin/env bash

หรือสำหรับสิ่งที่ภาษาเช่นสำหรับ Perl

#!/usr/bin/env perl

ให้แน่ใจว่าได้ดูmanหน้าสำหรับbash:

man bash

และenv:

man env

หมายเหตุ: ใน Debian และ Debian ที่ใช้ระบบเช่นอูบุนตูshจะเชื่อมโยงไปไม่ได้dash ในฐานะที่เป็นสคริปต์ทั้งหมดใช้ระบบbash shสิ่งนี้ช่วยให้ทุบตีเติบโตและระบบยังคงมีเสถียรภาพตาม Debian

นอกจากนี้เพื่อให้การเรียกใช้ * ระวังเหมือนฉันไม่เคยใช้ส่วนขยายของไฟล์ในสคริปต์ที่เรียกใช้ของ shebang เนื่องจากคุณไม่สามารถละเว้นส่วนขยายของการเรียกใช้งานบน executables ได้เช่นเดียวกับที่คุณทำบน Windows คำสั่ง file สามารถระบุว่าเป็นสคริปต์


4

มันขึ้นอยู่กับว่าคุณเขียนสคริปต์ทุบตีของคุณอย่างไร หากคุณ/bin/shมี symlinked เพื่อทุบตีเมื่อทุบตีถูกเรียกเป็นsh, คุณสมบัติบางอย่างจะไม่สามารถใช้ได้

หากคุณต้องการคุณสมบัติเฉพาะ bash เฉพาะที่ไม่ใช่ POSIX ให้ใช้ #!/bin/bash


3
ไม่ได้ติดตั้ง Bash ใน OpenBSD หากคุณติดตั้งผ่านpkg_addก็จะอยู่ใน/usr/local/binซึ่งอาจไม่อยู่ในเส้นทาง
jww

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