Bạn đã có nó lạc hậu. /bin/sh
gần như không bao giờ là vỏ Bourne ngày nay, và đó là khi bạn gặp vấn đề khi sử dụng #! /bin/sh
cô ấy.
Vỏ Bourne là một vỏ được viết vào cuối những năm 70 và thay thế cho vỏ Thompson trước đây (còn được gọi là sh
). Đầu những năm 80, David Korn đã viết một vài phần mở rộng cho shell Bourne, sửa một vài lỗi và sự lúng túng trong thiết kế (và giới thiệu một số) và gọi nó là shell Korn.
Đầu những năm 90, POSIX đã chỉ định sh
ngôn ngữ dựa trên một tập hợp con của vỏ Korn và hầu hết các hệ thống hiện đã thay đổi thành /bin/sh
vỏ Korn hoặc vỏ phù hợp với đặc điểm kỹ thuật đó. Trong trường hợp BSD, /bin/sh
ban đầu họ đã thay đổi (ban đầu (sau khi họ không còn có thể sử dụng vỏ Bourne vì lý do giấy phép), vỏ Almquist, một bản sao của vỏ Bourne với một số phần mở rộng ksh để nó trở thành tuân thủ POSIX.
Ngày nay, tất cả các hệ thống POSIX đều có vỏ được gọi sh
(thường xuyên nhất, nhưng không nhất thiết phải có /bin
, POSIX không chỉ định đường dẫn của các tiện ích mà nó chỉ định) mà hầu hết là tuân thủ POSIX. Nó thường dựa trên ksh88, ksh93, pdksh, bash, ash hoặc zsh², nhưng không phải là vỏ Bourne vì vỏ Bourne không bao giờ tuân thủ POSIX. Một vài trong số những vỏ ( bash
, zsh
, yash
và một số pdksh
dẫn xuất cho phép một chế độ POSIX-compliant khi gọi là sh
và ít phù hợp khác).
bash
(câu trả lời GNU cho shell Korn) thực sự là shell nguồn mở duy nhất (và người ta chỉ có thể nói hiện tại được duy trì vì những cái khác thường dựa trên ksh88 không có bất kỳ tính năng mới nào kể từ những năm 90) đã được chứng nhận là là một tiêu chuẩn POSIX sh
(như một phần của chứng nhận macOS).
Khi bạn viết một tập lệnh bằng một cú #! /bin/sh -
đánh, bạn nên sử dụng một sh
cú pháp tiêu chuẩn (và cũng nên sử dụng cú pháp tiêu chuẩn cho các tiện ích được sử dụng trong tập lệnh đó nếu bạn muốn có thể di động, nó không chỉ là trình bao có liên quan khi diễn giải trình bao tập lệnh), sau đó không quan trọng việc triển khai sh
trình thông dịch cú pháp chuẩn đó được sử dụng ( ksh
, bash
...).
Không có vấn đề gì khi những cái vỏ đó có phần mở rộng so với tiêu chuẩn miễn là bạn không sử dụng chúng. Nó giống như để viết mã C, miễn là bạn viết mã C tiêu chuẩn và không sử dụng các phần mở rộng của một trình biên dịch (như gcc
) hoặc khác, mã của bạn sẽ biên dịch OK bất kể việc triển khai trình biên dịch với điều kiện trình biên dịch tuân thủ.
Ở đây, với bạn #! /bin/sh
cô-bang, vấn đề chính của bạn sẽ là hệ thống mà /bin/sh
là Bourne shell rằng ví dụ không hỗ trợ tính năng tiêu chuẩn như $((1+1))
, $(cmd)
, ${var#pattern}
... Trong trường hợp này bạn có thể cần công việc ở quanh như:
#! /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
Nhân tiện, Ubuntu /bin/sh
không phải là bash
mặc định. Đó là dash
những ngày này, một lớp vỏ đó là dựa trên NetBSD sh
, bản thân dựa trên vỏ Almquist mà chủ yếu là POSIX compliant ngoại trừ việc nó không hỗ trợ ký tự nhiều byte. Trên Ubuntu và các hệ thống dựa trên Debian khác, bạn có thể chọn giữa bash
và dash
cho /bin/sh
với dpkg-reconfigure dash
) 4 . sh
các tập lệnh được cung cấp với Debian sẽ hoạt động giống nhau trong cả hai hệ vỏ vì chúng được ghi theo tiêu chuẩn chính sách Debian (siêu bộ của tiêu chuẩn POSIX). Có thể bạn sẽ thấy họ cũng làm việc OK trong zsh
's sh
thi đua hay bosh
(có lẽ không ksh93
hay yash
mà không có một local
BUILTIN (theo yêu cầu của chính sách Debian nhưng không phải POSIX)).
Tất cả các hệ thống trong phạm vi trên unix.stackexchange.com đều có POSIX sh
ở đâu đó. Hầu hết trong số họ có một /bin/sh
(bạn có thể tìm thấy những thư mục rất hiếm không có /bin
thư mục nhưng có lẽ bạn không quan tâm đến điều đó), và đó thường là sh
trình thông dịch POSIX (và trong một số trường hợp hiếm hoi là vỏ Bourne (không chuẩn) ).
Nhưng sh
là trình thông dịch shell duy nhất có thể thực thi mà bạn có thể chắc chắn tìm thấy trên một hệ thống. Đối với các shell khác, bạn có thể chắc chắn rằng các bản phân phối macOS, Cygwin và hầu hết các GNU / Linux sẽ có bash
. Các hệ điều hành có nguồn gốc từ SYSV (Solaris, AIX ...) thường sẽ có ksh88, có thể là ksh93. OpenBSD, MirOS sẽ có đạo hàm pdksh. macOS sẽ có zsh
. Nhưng trong số đó, sẽ không có gì đảm bảo. Không đảm bảo dù là bash
bất kỳ hoặc bất kỳ vỏ nào khác sẽ được cài đặt trong /bin
hoặc ở nơi khác (thường được tìm thấy trong /usr/local/bin
BSD khi được cài đặt chẳng hạn). Và tất nhiên không có gì đảm bảo phiên bản shell sẽ được cài đặt.
Lưu ý rằng đó #! /path/to/executable
không phải là một quy ước , đó là một tính năng của tất cả các hạt nhân giống Unix (được giới thiệu vào đầu những năm 80 bởi Dennis Ritchie ) cho phép thực thi các tệp tùy ý bằng cách chỉ định đường dẫn của trình thông dịch trong dòng đầu tiên bắt đầu bằng #!
. Nó có thể là bất kỳ thực thi.
Khi bạn thực thi một tệp có dòng đầu tiên bắt đầu #! /some/file some-optional-arg
, kernel sẽ kết thúc thực thi /some/file
với some-optional-arg
, đường dẫn của tập lệnh và các đối số ban đầu là đối số. Bạn có thể thực hiện dòng đầu tiên #! /bin/echo test
để xem những gì đang xảy ra:
$ ./myscript foo
test ./myscript foo
Khi bạn sử dụng /bin/sh -
thay vì /bin/echo test
, kernel sẽ thực thi /bin/sh - ./myscript foo
, sh
diễn giải mã nội dung được lưu trữ myscript
và bỏ qua dòng đầu tiên đó như là một nhận xét (bắt đầu bằng #
).
Ally Có lẽ hệ thống duy nhất hiện nay mà bất kỳ ai trong chúng ta sẽ bắt gặp một hệ thống /bin/sh
dựa trên vỏ Bourne là Solaris 10. Solaris là một trong số ít các Unice quyết định giữ vỏ Bourne ở đó để tương thích ngược ( sh
ngôn ngữ POSIX không hoàn toàn tương thích ngược với vỏ Bourne) và (ít nhất là cho các triển khai máy tính để bàn và máy chủ đầy đủ) có POSIX sh
ở nơi khác (trong /usr/xpg4/bin/sh
, dựa trên ksh88), nhưng điều đó đã thay đổi trong Solaris 11, /bin/sh
giờ là ksh93. Những người khác chủ yếu là không còn tồn tại.
² Các /bin/sh
của hệ điều hành MacOS / X sử dụng để đượczsh
, nhưng sau đó chuyển sang bash
. Đây không phải zsh
là trọng tâm chính được sử dụng làm sh
triển khai POSIX . sh
Chế độ của nó chủ yếu là để có thể nhúng hoặc gọi ( source
) sh
mã POSIX trong zsh
các tập lệnh
Gần đây, @schily đã mở rộng lớp vỏ OpenSolaris (dựa trên lớp vỏ SVR4, dựa trên lớp vỏ Bourne) để tuân thủ POSIX, được gọi bosh
nhưng tôi không biết rằng nó đã được sử dụng trên bất kỳ hệ thống nào. Cùng với ksh88
đó làm cho nó trở thành một vỏ tương thích POSIX thứ hai dựa trên mã của vỏ Bourne
4 Trong các phiên bản cũ hơn, bạn cũng có thể sử dụng mksh
hoặc lksh
hóa thân POSIX hơn . Đó là lớp vỏ MirOS (trước đây là MirBSD) dựa trên pdksh, bản thân nó dựa trên lớp vỏ Forsyth (một cách tái hiện khác của lớp vỏ Bourne))