คุณได้รับมันย้อนหลัง /bin/sh
แทบจะไม่เคยเป็นเชลล์เป้าหมายในทุกวันนี้และเมื่อไรที่คุณมีปัญหาเมื่อใช้#! /bin/sh
she-bang
เชลล์เป้าหมายเป็นเชลล์ที่เขียนในช่วงปลายยุค 70 และแทนที่เชลล์ ธ อมป์สันก่อนหน้านี้ (เรียกอีกอย่างว่าsh
) ในช่วงต้นทศวรรษที่ 80 David Korn เขียนส่วนขยายสำหรับเชลล์เป้าหมายขึ้นเล็กน้อยแก้ไขข้อบกพร่องบางประการและออกแบบความอึดอัดใจ (และแนะนำบางอย่าง) และเรียกมันว่า Korn เชลล์
ในช่วงต้น 90s, POSIX ระบุsh
ภาษาตามชุดย่อยของ Korn เชลล์และระบบส่วนใหญ่ตอนนี้เปลี่ยน/bin/sh
เป็น Korn เชลล์หรือเป็นไปตามข้อกำหนดของสเปคนั้น ในกรณีของ BSD พวกเขาค่อย ๆ เปลี่ยน/bin/sh
ในขั้นต้น (หลังจากพวกเขาไม่สามารถใช้เชลล์บอร์นสำหรับเหตุผลด้านลิขสิทธิ์อีกต่อไป) เชลล์ Almquist ซึ่งเป็นโคลนนิ่งเชลล์บอร์นที่มีนามสกุล ksh บางส่วนจึงกลายเป็น POSIX ที่สอดคล้องกัน
ทุกวันนี้ระบบ POSIX ทั้งหมดมีเชลล์ชื่อsh
(ส่วนใหญ่ แต่ไม่จำเป็นต้องมีใน/bin
POSIX ไม่ได้ระบุพา ธ ของยูทิลิตีที่ระบุ) ซึ่งส่วนใหญ่เป็นไปตาม POSIX โดยทั่วไปแล้วจะขึ้นอยู่กับ ksh88, ksh93, pdksh, bash, ash หรือzsh² แต่ไม่ใช่เชลล์ Bourne เนื่องจากเชลล์ Bourne ไม่รองรับ POSIX ไม่กี่ของเปลือกหอยเหล่านั้น ( bash
, zsh
, yash
และบางpdksh
อนุพันธ์เปิดใช้งานโหมด POSIX สอดคล้องเมื่อเรียกเป็นsh
และน้อยตามมาตรฐานอื่น ๆ )
bash
(คำตอบของ GNU ต่อ Korn เชลล์) เป็นจริงของโอเพ่นซอร์สเชลล์เท่านั้น (และใคร ๆ ก็สามารถพูดได้ว่าปัจจุบันได้รับการบำรุงรักษาเท่านั้นเนื่องจากโดยทั่วไปแล้วจะอ้างอิง ksh88 ซึ่งไม่ได้รับฟีเจอร์ใหม่ตั้งแต่ 90s) ที่ได้รับการรับรองว่า เป็นไปตาม POSIX sh
(เป็นส่วนหนึ่งของการรับรอง macOS)
เมื่อคุณเขียนสคริปต์ด้วย#! /bin/sh -
she-bang คุณควรใช้sh
ไวยากรณ์มาตรฐาน(และควรใช้ไวยากรณ์มาตรฐานสำหรับยูทิลิตี้ที่ใช้ในสคริปต์นั้นหากคุณต้องการพกพาไม่ใช่แค่เชลล์ที่เกี่ยวข้องเมื่อตีความเชลล์ สคริปต์) จากนั้นไม่สำคัญว่าการใช้งานของsh
ล่ามไวยากรณ์มาตรฐานนั้นจะใช้ ( ksh
, bash
... )
ไม่สำคัญว่าเชลล์เหล่านั้นจะมีส่วนขยายเกินมาตรฐานตราบใดที่คุณไม่ได้ใช้งาน มันเหมือนกับการเขียนรหัส C ตราบใดที่คุณเขียนรหัส C มาตรฐานและไม่ใช้ส่วนขยายของคอมไพเลอร์หนึ่ง (เช่นgcc
) หรืออื่น ๆ โค้ดของคุณควรคอมไพล์ตกลงโดยไม่คำนึงถึงการใช้คอมไพเลอร์ที่คอมไพเลอร์
ที่นี่กับ#! /bin/sh
เธอปัง, ปัญหาหลักของคุณจะเป็นระบบที่/bin/sh
เป็นบอร์นเชลล์ที่เช่นไม่สนับสนุนคุณลักษณะมาตรฐานเช่น$((1+1))
, $(cmd)
, ${var#pattern}
... ซึ่งในกรณีนี้คุณอาจต้องทำงาน arounds ที่ชอบ:
#! /bin/sh -
if false ^ true; then
# in the Bourne shell, ^ is an alias for |, so false ^ true returns
# true in the Bourne shell and the Bourne shell only.
# Assume the system is Solaris 10 (older versions are no longer maintained)
# You would need to adapt if you need to support some other system
# where /bin/sh is the Bourne shell.
# We also need to fix $PATH as the other utilities in /bin are
# also ancient and not POSIX compatible.
PATH=`/usr/xpg6/bin/getconf PATH`${PATH:+:}$PATH || exit
export PATH
exec /usr/xpg4/bin/sh "$0" "$@"
# that should give us an environment that is mostly compliant
# to the Single UNIX Specification version 3 (POSIX.2004), the
# latest supported by Solaris 10.
fi
# rest of the script
อย่างไรก็ตาม Ubuntu /bin/sh
ไม่ได้เป็นbash
ค่าเริ่มต้น มันเป็นdash
วันนี้เชลล์ที่อยู่บนพื้นฐานของ NetBSD sh
ตัวเองอยู่บนพื้นฐานของ Almquist เปลือกซึ่งส่วนใหญ่ตาม POSIX ยกเว้นว่าจะไม่สนับสนุนอักขระหลายไบต์ บน Ubuntu และระบบที่ใช้เดเบียนอื่น ๆ คุณสามารถเลือกระหว่างbash
และdash
สำหรับ/bin/sh
ด้วยdpkg-reconfigure dash
) 4 sh
สคริปต์ที่มาพร้อมกับ Debian ควรทำงานเหมือนกันในทั้งสองเชลล์เนื่องจากจะถูกเขียนไปยังมาตรฐานนโยบาย Debian (superset ของมาตรฐาน POSIX) คุณอาจจะพบว่าพวกเขายังตกลงในการทำงานzsh
ของsh
การจำลองหรือbosh
(อาจจะไม่ksh93
มิได้yash
ซึ่งไม่ได้มีlocal
ในตัว (ต้องตามนโยบาย Debian แต่ไม่ POSIX))
ระบบทั้งหมดในขอบเขตบน unix.stackexchange.com มี POSIX ที่sh
ใดที่หนึ่ง ส่วนใหญ่มี/bin/sh
(คุณอาจพบสิ่งที่หายากมากที่ไม่มี/bin
ไดเรกทอรี แต่คุณอาจไม่สนใจเรื่องนั้น) และโดยทั่วไปแล้วsh
ล่ามPOSIX (และในกรณีที่หายากเปลือก Bourne (ที่ไม่ได้มาตรฐาน) แทน )
แต่sh
เป็นล่ามเชลล์ตัวเดียวที่สามารถเรียกใช้งานได้คุณสามารถค้นหาบนระบบได้ สำหรับเปลือกหอยอื่น ๆ ที่คุณสามารถมั่นใจได้ MacOS, Cygwin และการแจกแจงที่สุด GNU / Linux bash
จะมี ระบบปฏิบัติการที่ได้รับจาก SYSV (Solaris, AIX ... ) โดยทั่วไปจะมี ksh88 อาจเป็น ksh93 OpenBSD, MirOS จะมีอนุพันธ์ pdksh MacOS zsh
จะมี แต่จากนั้นจะไม่มีการรับประกัน ไม่มีการรับประกันไม่ว่าbash
จะมีการติดตั้งเชลล์อื่น ๆ หรือเชลล์/bin
อื่น ๆ (โดยทั่วไปจะพบใน/usr/local/bin
BSD เมื่อติดตั้งเป็นต้น) และแน่นอนไม่มีการรับประกันเวอร์ชันของเชลล์ที่จะติดตั้ง
สังเกตว่า #! /path/to/executable
ไม่ได้เป็นการประชุมก็คุณสมบัติทั้งหมดของระบบปฏิบัติการยูนิกซ์เหมือนเมล็ด ( เปิดตัวในช่วงต้นยุค 80 โดยเดนนิสริตชี่ ) #!
ที่ช่วยให้รันไฟล์โดยพลการโดยการระบุเส้นทางของล่ามในบรรทัดแรกที่เริ่มต้นด้วย มันสามารถปฏิบัติการได้
เมื่อคุณเรียกใช้งานไฟล์ที่บรรทัดแรกขึ้นต้นด้วย #! /some/file some-optional-arg
เคอร์เนลจะจบลง/some/file
ด้วยการดำเนินsome-optional-arg
การพา ธ ของสคริปต์และอาร์กิวเมนต์ดั้งเดิมเป็นอาร์กิวเมนต์ คุณสามารถสร้างบรรทัดแรก#! /bin/echo test
เพื่อดูว่าเกิดอะไรขึ้น:
$ ./myscript foo
test ./myscript foo
เมื่อคุณใช้/bin/sh -
แทน/bin/echo test
, รันเคอร์เนล/bin/sh - ./myscript foo
, sh
ตีความรหัสเนื้อหาที่เก็บไว้ในmyscript
และละเว้นที่บรรทัดแรกเป็นมันความคิดเห็น (เริ่มต้นด้วย#
)
¹อาจเป็นระบบเดียวในวันนี้ที่พวกเราทุกคนจะเจอ /bin/sh
ที่อยู่บนพื้นฐานของบอร์นเปลือก Solaris 10 Solaris เป็นหนึ่งในไม่กี่ Unices ที่ตัดสินใจที่จะเก็บเปลือกบอร์นมีความเข้ากันได้ย้อนหลัง (คน POSIX sh
ภาษาไม่ได้อย่างเต็มที่ เข้ากันได้ย้อนหลังกับ Bourne shell) และ (อย่างน้อยสำหรับเดสก์ท็อปและการปรับใช้เซิร์ฟเวอร์แบบเต็ม) มี POSIX sh
ที่อื่น (ใน/usr/xpg4/bin/sh
, ขึ้นอยู่กับ ksh88) แต่เปลี่ยนไปใน Solaris 11 ซึ่ง/bin/sh
ตอนนี้เป็น ksh93 คนอื่น ๆ ส่วนใหญ่จะตาย
² ของ MacOS / X เคยเป็นแต่ต่อมาเปลี่ยนเป็น ไม่ใช่จุดสนใจหลักที่จะใช้เป็นการนำPOSIX มาใช้ ของมัน/bin/sh
zsh
bash
zsh
sh
sh
โหมดเป็นหลักเพื่อให้สามารถฝังหรือโทร ( source
) POSIX sh
รหัสในzsh
สคริปต์
³เมื่อเร็ว ๆ นี้@schilyขยายเชลล์ OpenSolaris (ฐานบนเชลล์ SVR4 ตามเชลล์เป้าหมาย) เพื่อให้เป็นไปตาม POSIX ที่เรียกว่าbosh
แต่ฉันไม่ทราบว่ามันใช้กับระบบใด ๆ พร้อมกับksh88
ที่ทำให้มันเป็นเปลือกที่สอดคล้องกับ POSIX ที่สองตามรหัสของเชลล์เป้าหมาย
4ในเวอร์ชั่นที่เก่ากว่าคุณสามารถใช้mksh
หรือการlksh
จุติPOSIX ได้มากกว่า นั่นคือเปลือก MirOS (เดิมคือ MirBSD) ที่ใช้ pdksh ซึ่งเป็นตัวของตัวเองตามเชลล์ Forsyth (การปรับใช้ใหม่อีกครั้งของ Bourne shell)