Umumnya, skrip shell berisi komentar berikut pada baris pertama dari file script: #!/bin/sh
. Menurut penelitian yang saya buat, ini disebut "hash bang" dan ini adalah komentar konvensional. Komentar ini memberi tahu Unix bahwa file ini dijalankan oleh Bourne Shell di bawah direktori /bin
.
Pertanyaan saya dimulai pada saat itu. Sampai sekarang saya belum melihat komentar ini seperti #!/bin/bash
. Selalu begitu #!/bin/sh
. Namun, distribusi Ubuntu tidak memiliki program Bourne Shell. Mereka memiliki Bourne Again Shell (bash).
Dalam hal itu, apakah benar menempatkan komentar #!/bin/sh
dalam skrip shell yang ditulis dalam distribusi Ubuntu?
shebang
Jawaban:
#!/bin/sh
harus bekerja pada semua distribusi Unix dan Unix-like. Biasanya dianggap sebagai hashbang paling portabel selama skrip Anda tetap sesuai dengan POSIX. The/bin/sh
shell seharusnya shell yang menerapkan POSIX shell standar, terlepas dari apa shell yang sebenarnya adalah bahwa menyamar sebagai/bin/sh
shell.#!/bin/sh
biasanya hanya sebuah tautan sekarang karena shell Bourne tidak lagi dipertahankan. Pada banyak sistem Unix/bin/sh
akan menjadi tautan ke/bin/ksh
atau/bin/ash
, pada banyak sistem Linux berbasis RHEL, itu akan menjadi tautan/bin/bash
, namun pada Ubuntu dan banyak sistem berbasis Debian, tautannya/bin/dash
. Semua shell, jika dipanggil sebagaish
, akan memasuki mode kompatibilitas POSIX.Hashbang adalah pengganti yang penting karena memungkinkan portabilitas yang jauh lebih besar daripada metode lain, selama skrip Anda benar-benar sesuai dengan POSIX (diulangi untuk menekankan pentingnya).
Catatan: Ketika
bash
dipanggil dalam mode POSIX itu masih akan memungkinkan beberapa hal non-POSIX seperti[[
, array, dan banyak lagi. Hal-hal itu mungkin gagal pada non-bash
sistem.sumber
/bin/ash
.#! /
bukan hanya#!
.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 beberapapdksh
turunannya memungkinkan modus POSIX-compliant ketika dipanggil sebagaish
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 compliantsh
(sebagai bagian dari sertifikasi macOS).Saat Anda menulis skrip dengan
#! /bin/sh -
she-bang, Anda harus menggunakansh
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 darish
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 (seperti
gcc
) 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:By the way, Ubuntu
/bin/sh
tidakbash
secara default. Sekarangdash
ini, sebuah shell yang didasarkan pada NetBSDsh
, 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 antarabash
dandash
untuk/bin/sh
dengandpkg-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 dizsh
'ssh
emulasi ataubosh
(mungkin tidakksh93
atauyash
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 memilikinyabash
. OS yang diturunkan SYSV (Solaris, AIX ...) umumnya akan memiliki ksh88, mungkin ksh93. OpenBSD, MirOS akan memiliki turunan pdksh. macOS akan memilikizsh
. Tapi di luar itu, tidak akan ada jaminan. Tidak ada jaminan apakahbash
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
dengansome-optional-arg
, jalur script dan argumen asli sebagai argumen. Anda dapat membuat baris pertama#! /bin/echo test
untuk melihat apa yang terjadi:Ketika Anda menggunakan
/bin/sh -
alih-alih/bin/echo test
, kernel mengeksekusi/bin/sh - ./myscript foo
,sh
menginterpretasikan kode konten yang disimpan dalammyscript
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 dish
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 menjadibash
. Ini bukanzsh
fokus utama untuk digunakan sebagaish
implementasi POSIX . Itssh
modus terutama untuk dapat embed atau panggilan (source
) POSIXsh
kodezsh
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 denganksh88
itu menjadikannya shell yang kompatibel dengan POSIX kedua berdasarkan kode shell Bourne4 Dalam versi yang lebih lama, Anda juga bisa menggunakan
mksh
atau lebihlksh
inkarnasi POSIX . Itulah shell MirOS (sebelumnya MirBSD) berdasarkan pdksh, itu sendiri berdasarkan pada shell Forsyth (implementasi lain dari shell Bourne))sumber
exec sh "$0" "$@"
setelah pengaturanPATH
? Itu seharusnya mengambilsh
dari tempat yang benar, saya akan berpikir.$PATH
.$(...)
, mode emacs / vi, ekspansi tilde / brace (yang awalnya dari csh), fc, typeset, alias , sintaks fungsi ksh-style ...Ya, Anda dapat menggunakan
#!/bin/sh
skrip karena/bin/sh
(semoga) disediakan untuk sistem seperti itu, biasanya melalui tautan semacam yang membuatbash
berperilaku (lebih atau kurang) seperti sebuahsh
wasiat. Berikut adalah sistem Centos7, misalnya, yang menghubungkansh
kebash
:Anda juga dapat menggunakan
#!/bin/bash
jika Anda menulisbash
skrip hanya untuk sistem itu dan ingin menggunakanbash
fitur. Namun, skrip tersebut akan mengalami masalah portabilitas, misalnya pada OpenBSD di manabash
hanya diinstal jika admin mengambil masalah untuk menginstalnya (saya tidak) dan kemudian diinstal ke/usr/local/bin/bash
, bukan/bin/bash
.#!/bin/sh
Skrip POSIX yang ketat harus lebih portabel.sumber
sh
, Bash memasuki mode POSIX setelah membaca file startup." - gnu.org/software/bash/manual/bashref.html#Bash-POSIX-Mode#!/bin/bash
tepat sehingga saya dapat memanfaatkan fitur-fitur non-POSIX./bin/sh
itu adalah symlinkbash
, apakah itu benar? Tapi saya tahu pasti pada CentOS.bash
. Biner itu tahu nama apa yang digunakan untuk memanggilnya, dan ketika itu disebutsh
itu bertindak seperti Bourne jadulsh
.Kamu bertanya
Jawabannya tergantung pada apa yang Anda tulis di skrip shell.
Jika Anda benar-benar menggunakan skrip yang kompatibel dengan POSIX portabel, dan tidak menggunakan perintah khusus bash, maka Anda dapat menggunakan
/bin/sh
.Jika Anda tahu bahwa Anda hanya pernah menggunakan skrip pada mesin dengan bash, dan Anda ingin menggunakan sintaks spesifik bash, maka Anda harus menggunakan
/bin/bash
Jika Anda ingin memastikan bahwa skrip akan bekerja pada bermacam-macam mesin unix, maka Anda harus menggunakan hanya sintaks yang sesuai dengan POSIX, dan
/bin/sh
Jika Anda secara teratur menggunakan shell lain (misalnya ksh , zsh atau Tcsh ), dan ingin menggunakan sintaks yang dalam naskah Anda, maka Anda harus menggunakan penerjemah yang sesuai (seperti
/bin/ksh93
,/bin/zsh
, atau/bin/tcsh
)sumber
"#!" komentar tidak selalu menggunakan
/bin/bash
atau/bin/sh
. Itu hanya mencantumkan apa pun penerjemah yang seharusnya, bukan hanya untuk skrip shell. Misalnya skrip python saya biasanya mulai dengan#!/usr/bin/env python
.Sekarang perbedaan antara
#!/bin/sh
dan#!/bin/bash
apakah itu/bin/sh
tidak selalu merupakan symlink ke/bin/bash
. Seringkali tetapi tidak selalu. Ubuntu adalah pengecualian di sini. Saya telah melihat skrip bekerja dengan baik pada CentOS tetapi gagal pada Ubuntu karena penulis menggunakan sintaks khusus bash dengan#!/bin/sh
.sumber
Maaf untuk menuangkan air dingin pada semua jawaban-jawaban besar yang mengatakan bahwa
/bin/sh
hadir di semua sistem Unix - itu ada, kecuali di sistem Unix yang paling sering digunakan: Android.Android memiliki cangkangnya
/system/bin/sh
, dan biasanya tidak ada cara untuk membuat/bin/sh
tautan, bahkan pada sistem yang sudah di-rooting (karena cara sistem dikunci dengan menggunakan selinux dan kemampuan (7) set pembatas).Bagi mereka yang akan mengatakan bahwa android tidak sesuai dengan POSIX: tidak semua distribusi Linux dan BSD. Dan keberadaan
/bin/sh
dengan jalan ini tidak diamanatkan oleh standar :sumber
getconf
? Misalnya pada Solaris 11.4, apakah itu yang ada di dalam/usr/bin
? Yang di/usr/xpg4/bin
(untuk kepatuhan SUSv2), yang di/usr/xpg6/bin
(untuk kepatuhan SUSv3)?/usr/xpg7/bin
(untuk SUSv4)?/bin/sh