Anda mendapatkannya mundur. /bin/sh
hampir tidak pernah menjadi Bourne shell hari ini, dan saat itulah it's Anda memiliki masalah ketika Anda menggunakan #! /bin/sh
bang-bang.
Cangkang Bourne adalah cangkang yang ditulis pada akhir 70-an dan menggantikan cangkang Thompson sebelumnya (juga disebut sh
). Pada awal 80-an, David Korn menulis beberapa ekstensi untuk shell Bourne, memperbaiki beberapa bug dan mendesain kecanggungan (dan memperkenalkan beberapa) dan menyebutnya shell Korn.
Pada awal 90-an, POSIX menentukan sh
bahasa berdasarkan subset dari shell Korn dan sebagian besar sistem sekarang telah mengubah mereka /bin/sh
menjadi shell Korn atau shell yang sesuai dengan spesifikasi itu. Dalam kasus BSD, mereka secara bertahap mengubah /bin/sh
, awalnya (setelah mereka tidak bisa lagi menggunakan shell Bourne untuk alasan lisensi) shell Almquist, klon dari shell Bourne dengan beberapa ekstensi ksh sehingga menjadi sesuai dengan POSIX.
Saat ini, semua sistem POSIX memiliki shell yang disebut sh
(paling sering, tetapi tidak harus dalam /bin
, POSIX tidak menentukan jalur utilitas yang ditentukan) yang sebagian besar sesuai dengan POSIX. Biasanya didasarkan pada ksh88, ksh93, pdksh, bash, ash atau zsh², tetapi tidak pada shell Bourne karena shell Bourne tidak pernah sesuai dengan POSIX³. Beberapa dari mereka kerang ( bash
, zsh
, yash
dan beberapa pdksh
turunannya memungkinkan modus POSIX-compliant ketika dipanggil sebagai sh
dan kurang compliant sebaliknya).
bash
(jawaban GNU ke shell Korn) sebenarnya adalah satu-satunya shell open source (dan bisa dikatakan hanya saat ini dipertahankan karena yang lain umumnya didasarkan pada ksh88 yang belum mendapatkan fitur baru sejak 90-an) yang telah disertifikasi sebagai menjadi POSIX compliant sh
(sebagai bagian dari sertifikasi macOS).
Saat Anda menulis skrip dengan #! /bin/sh -
she-bang, Anda harus menggunakan sh
sintaksis standar (dan juga harus menggunakan sintaksis standar untuk utilitas yang digunakan dalam skrip itu jika Anda ingin portabel, itu bukan hanya shell yang terlibat saat menafsirkan shell skrip), maka tidak masalah implementasi apa dari sh
interpreter sintaks standar yang digunakan ( ksh
, bash
...).
Tidak masalah bahwa cangkang tersebut memiliki ekstensi melebihi standar selama Anda tidak menggunakannya. Ini seperti untuk menulis kode C, selama Anda menulis kode C standar dan tidak menggunakan ekstensi satu kompiler (sepertigcc
) atau yang lain, kode Anda harus dikompilasi OK terlepas dari implementasi kompiler asalkan kompiler sesuai.
Di sini, dengan Anda #! /bin/sh
dia-bang, masalah utama Anda akan menjadi sistem di mana /bin/sh
adalah Bourne shell yang misalnya tidak mendukung fitur standar seperti $((1+1))
, $(cmd)
, ${var#pattern}
... Dalam hal ini Anda mungkin perlu kerja-arounds seperti:
#! /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
By the way, Ubuntu /bin/sh
tidak bash
secara default. Sekarang dash
ini, sebuah shell yang didasarkan pada NetBSD sh
, itu sendiri berdasarkan pada shell Almquist yang sebagian besar sesuai dengan POSIX kecuali bahwa ia tidak mendukung karakter multi-byte. Di Ubuntu dan sistem berbasis Debian lainnya, Anda dapat memilih antara bash
dan dash
untuk /bin/sh
dengan dpkg-reconfigure dash
) 4 . sh
skrip yang dikirimkan dengan Debian harus bekerja sama di kedua shell karena ditulis ke standar kebijakan Debian (superset dari standar POSIX). Anda mungkin akan menemukan mereka juga bekerja OK di zsh
's sh
emulasi atau bosh
(mungkin tidak ksh93
atau yash
yang tidak memilikilocal
builtin (yang dibutuhkan oleh kebijakan Debian tapi tidak POSIX)).
Semua sistem dalam lingkup di unix.stackexchange.com memiliki POSIX di sh
suatu tempat. Kebanyakan dari mereka memiliki /bin/sh
(Anda mungkin menemukan yang sangat jarang yang tidak memiliki /bin
direktori tetapi Anda mungkin tidak peduli tentang itu), dan itu umumnya POSIXsh
penerjemah (dan dalam kasus yang jarang terjadi, Bourne shell (non-standar) sebagai gantinya ).
Tetapi sh
apakah satu-satunya shell interpreter yang dapat dieksekusi dapat Anda temukan pada suatu sistem. Untuk shell lainnya, Anda dapat yakin macOS, Cygwin dan sebagian besar distribusi GNU / Linux akan memilikinya bash
. OS yang diturunkan SYSV (Solaris, AIX ...) umumnya akan memiliki ksh88, mungkin ksh93. OpenBSD, MirOS akan memiliki turunan pdksh. macOS akan memiliki zsh
. Tapi di luar itu, tidak akan ada jaminan. Tidak ada jaminan apakah bash
shell yang lain akan dipasang di /bin
atau di tempat lain (biasanya ditemukan /usr/local/bin
pada BSD ketika diinstal misalnya). Dan tentu saja tidak ada jaminan versi shell yang akan diinstal.
Perhatikan bahwa #! /path/to/executable
ini bukan konvensi , ini adalah fitur dari semua kernel mirip Unix ( diperkenalkan pada awal 80-an oleh Dennis Ritchie ) yang memungkinkan mengeksekusi file sewenang-wenang dengan menentukan jalur penerjemah dalam baris pertama yang dimulai dengan #!
. Itu bisa saja dapat dieksekusi.
Ketika Anda menjalankan sebuah file yang pertama baris dimulai dengan #! /some/file some-optional-arg
, kernel berakhir mengeksekusi /some/file
dengan some-optional-arg
, jalur script dan argumen asli sebagai argumen. Anda dapat membuat baris pertama #! /bin/echo test
untuk melihat apa yang terjadi:
$ ./myscript foo
test ./myscript foo
Ketika Anda menggunakan /bin/sh -
alih-alih /bin/echo test
, kernel mengeksekusi /bin/sh - ./myscript foo
, sh
menginterpretasikan kode konten yang disimpan dalam myscript
dan mengabaikan baris pertama itu sebagai komentar (dimulai dengan #
).
¹ Mungkin satu-satunya sistem hari ini di mana salah satu dari kita akan menemukan /bin/sh
yang didasarkan pada cangkang Bourne adalah Solaris 10. Solaris adalah salah satu dari beberapa Unices yang memutuskan untuk menyimpan cangkang Bourne di sana untuk kompatibilitas ke belakang ( sh
bahasa POSIX tidak sepenuhnya kompatibel dengan shell Bourne) dan (setidaknya untuk penyebaran desktop dan server penuh) memiliki POSIX di sh
tempat lain (masuk /usr/xpg4/bin/sh
, berdasarkan ksh88), tetapi itu berubah di Solaris 11 di mana /bin/sh
sekarang ksh93. Yang lain sebagian besar mati.
² The /bin/sh
MacOS / X duluzsh
, tetapi kemudian berubah menjadi bash
. Ini bukan zsh
fokus utama untuk digunakan sebagai sh
implementasi POSIX . Its sh
modus terutama untuk dapat embed atau panggilan ( source
) POSIX sh
kode zsh
skrip
³ Baru-baru ini, @schily memperpanjang cangkang OpenSolaris (berdasarkan cangkang SVR4, berdasarkan cangkang Bourne) untuk menjadi sesuai dengan POSIX, dipanggil bosh
tetapi saya tidak tahu bahwa itu digunakan pada sistem apa pun. Bersamaan dengan ksh88
itu menjadikannya shell yang kompatibel dengan POSIX kedua berdasarkan kode shell Bourne
4 Dalam versi yang lebih lama, Anda juga bisa menggunakan mksh
atau lebih lksh
inkarnasi POSIX . Itulah shell MirOS (sebelumnya MirBSD) berdasarkan pdksh, itu sendiri berdasarkan pada shell Forsyth (implementasi lain dari shell Bourne))