อะไรคือความแตกต่างระหว่าง #! / bin / sh และ #! / bin / bash?


280

ถ้าฉันเขียน

#!/bin/bash
echo "foo"

หรือ

#!/bin/sh
echo "foo"

ทั้งสองให้ผลเหมือนกัน ผมเคยเห็นบางสคริปต์ที่เริ่มต้นด้วยหรือ#!/bin/sh #!/bin/bashมีความแตกต่างระหว่างพวกเขาหรือไม่?

คำตอบ:


242

bashและshเป็นเปลือกหอยสองแบบ โดยทั่วไปbashคือshมีคุณสมบัติมากขึ้นและไวยากรณ์ที่ดีกว่า คำสั่งส่วนใหญ่ทำงานเหมือนกัน แต่แตกต่างกัน

ต้องบอกว่าคุณควรตระหนักในระบบส่วนใหญ่จะมีการเชื่อมโยงสัญลักษณ์และจะไม่ก่อให้เกิด/bin/sh shใน Ubuntu /bin/shที่ใช้ในการเชื่อมโยงไปยังbashพฤติกรรมทั่วไปบนลินุกซ์ แต่ตอนนี้มีการเปลี่ยนแปลงที่จะเชื่อมโยงไปยังอีกที่เรียกว่าเปลือกประ ฉันจะใช้bashเนื่องจากเป็นมาตรฐาน (หรืออย่างน้อยที่สุดจากประสบการณ์ของฉัน) ในความเป็นจริงแล้วปัญหาเกิดขึ้นเมื่อสคริปต์ทุบตีจะใช้#!/bin/shเพราะผู้สร้างสคริปต์สันนิษฐานว่าการเชื่อมโยงคือbashเมื่อไม่จำเป็นต้องเป็น

สำหรับข้อมูลเพิ่มเติมhttp://man.cx/sh , http://man.cx/bash


24
ย่อหน้าแรกของคุณค่อนข้างทำให้เข้าใจผิด "sh" ไม่ใช่เชลล์เลย แต่เป็น symlink ไปยังเชลล์ระบบที่กำหนดค่าไว้ในปัจจุบันซึ่งบนระบบ Linux นั้นมักจะเป็น bash หรือ dash (Ubuntu รุ่นล่าสุดที่ใช้หลัง)
thomasrutter

18
/bin/shเคยเป็นเปลือกที่เรียกว่าเปลือกbourneย้อนกลับไปในปี 1977 ทุบตีเป็นเปลือกเข้ากันได้ / bin / sh ที่สามารถใช้เป็นทดแทนเปลือก bourne ที่เป็นไปตาม posix en.wikipedia.org/wiki/Bourne_shell
Alex

5
ทุบตีเป็นมาตรฐานพฤตินัย (ใช้กันอย่างแพร่หลายมาก) แต่มันไม่ได้เป็น "มาตรฐาน"; shบน Ubuntu ใช้เส้นประซึ่งเป็นเชลล์ที่สอดคล้องกับ Posix ดังนั้นจึงเป็นมาตรฐานจริงๆ คำแนะนำของฉันคือใช้แดชบ่อยเท่าที่เป็นไปได้สำหรับการเขียนสคริปต์โดยเฉพาะอย่างยิ่งสำหรับสคริปต์ฝั่งเซิร์ฟเวอร์ แม้ว่าbashนั้นจะแสดงออกได้มากกว่า แต่dash ก็วิ่งได้เร็วกว่าและปลอดภัยกว่า
Rick-777

@ Rick-777 ดังนั้นฉันควรใส่ #! / bin / dash ไว้ที่ด้านบนสุดของสคริปต์หรือไม่ ฉันยังได้เขียนสคริปต์ที่ฉันเพียงเขียนคำสั่งและดำเนินการด้วย. sscriptName และทำงานได้ดี #! / bin / yourShellHere จำเป็นหรือไม่
user137717

@ Rick-777 ในกรณีที่ฉันยกเว้น #! / bin / shellName ใด ๆ ฉันได้ตั้งชื่อไฟล์ fileName.sh สิ่งนั้นจะเชื่อมโยงกับเชลล์ระบบที่ต้องการโดยไม่ต้องประกาศ #! / bin / sh หรือไม่
user137717

82

บน Linux และระบบที่คล้าย Unix อื่น ๆ คุณสามารถเลือกได้หลายเชลล์

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

bashเป็นเชลล์ทั่วไปที่ใช้เป็นเชลล์เริ่มต้นสำหรับผู้ใช้ระบบ Linux มันคือการสืบทอดทางวิญญาณของกระสุนอื่น ๆ ที่ใช้ในประวัติศาสตร์ Unix ชื่อของมันทุบตีเป็นตัวย่อของ Bourne-Again Shell เป็นการแสดงความเคารพต่อ Bourne shell ที่ถูกออกแบบมาเพื่อแทนที่แม้ว่ามันจะรวมเอาคุณสมบัติต่างๆจาก C Shell และ Korn Shell

มันทำงานตั้งแต่วันนี้/bin/bash- ระบบใด ๆ ที่มี bash จะสามารถเข้าถึงได้ที่นี่

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

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

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

bin / sh /เป็นปฏิบัติการที่เป็นตัวแทนของเปลือกระบบ ที่จริงแล้วมันมักจะถูกนำไปใช้เป็นลิงค์สัญลักษณ์ที่ชี้ไปที่ปฏิบัติการสำหรับเชลล์ใดก็ตามที่เป็นเชลล์ระบบ เชลล์ของระบบเป็นชนิดของเชลล์เริ่มต้นที่สคริปต์ระบบควรใช้ ในลีนุกซ์ดิสทริบิวชั่นเป็นเวลานานซึ่งโดยปกติจะเป็นลิงก์สัญลักษณ์ไปยังbashดังนั้นมันจึงกลายเป็นรูปแบบการประชุมที่มักจะลิงค์ / bin / sh ไปยัง bash หรือเชลล์ที่ใช้ร่วมกันได้ อย่างไรก็ตามในช่วงสองสามปีที่ผ่านมา Debian (และ Ubuntu) ได้ตัดสินใจเปลี่ยนเชลล์ระบบจาก bash เป็นdash- เชลล์ที่คล้ายกัน - ทำลายด้วยประเพณีอันยาวนานใน Linux (ดี GNU) ของการใช้ bash สำหรับ / bin / sh Dash ถูกมองว่าเป็นเชลล์ที่เบากว่าและเร็วกว่ามากซึ่งเป็นประโยชน์ต่อความเร็วในการบูต (และสิ่งอื่น ๆ ที่ต้องการเชลล์สคริปต์จำนวนมากเช่นสคริปต์การติดตั้งแพ็กเกจ)

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

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

สิ่งที่คุณควรใช้เมื่อเขียนสคริปต์

#!/bin/bashหากสคริปต์ของคุณต้องมีคุณสมบัติการสนับสนุนจากการทุบตีการใช้งานเท่านั้น

แต่ถ้าเป็นไปได้ควรตรวจสอบให้แน่ใจว่าสคริปต์ของคุณเข้ากันได้กับ POSIX และใช้งาน#!/bin/shซึ่งควรเชื่อถือได้อย่างแน่นอนชี้ไปที่เชลล์ระบบที่รองรับ POSIX ที่ต้องการในการติดตั้งใด ๆ


18

นอกจากนี้ในการตอบก่อนหน้านี้แม้ว่า/bin/shเป็น symbolic link ไป/bin/bash, ไม่ได้โดยสิ้นเชิงเทียบเท่ากับ#!/bin/sh#!/bin/bash

จากหน้าคนทุบตี (1) :

"ถ้า bash ถูกเรียกด้วยชื่อ sh มันจะพยายามเลียนแบบพฤติกรรมการเริ่มต้นของ sh รุ่นที่ผ่านมามากที่สุดเท่าที่จะทำได้ในขณะที่สอดคล้องกับมาตรฐาน POSIX เช่นกัน"

ตัวอย่างเช่นไวยากรณ์เฉพาะของ bash:

 exec  > >(tee logfile.txt)

ให้ข้อผิดพลาดในเชลล์ที่ขึ้นต้นด้วย#!/bin/shแม้จะมี sh-> bash symbolic link อยู่


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