Ogólnie, skrypty powłoki zawierają następujący komentarz w pierwszym wierszu pliku skryptu: #!/bin/sh
. Według przeprowadzonych przeze mnie badań nazywa się to „hash bang” i jest to konwencjonalny komentarz. Ten komentarz informuje Unixa, że ten plik jest wykonywany przez Bourne Shell w katalogu /bin
.
Moje pytanie zaczyna się od tego momentu. Do tej pory nie widziałem tego komentarza #!/bin/bash
. Tak jest zawsze #!/bin/sh
. Jednak dystrybucje Ubuntu nie mają programu Bourne Shell. Mają Bourne Again Shell (bash).
Czy w tym momencie poprawne jest umieszczanie komentarza #!/bin/sh
w skryptach powłoki napisanych w dystrybucjach Ubuntu?
shebang
Odpowiedzi:
#!/bin/sh
powinien działać na wszystkich dystrybucjach uniksowych i podobnych. Jest to ogólnie uważane za najbardziej przenośny hashbang, o ile skrypt jest zgodny z POSIX./bin/sh
Powłoka ma być powłoką, która implementuje powłoki POSIX standard, niezależnie od tego, co rzeczywiste jest to, że powłoka maskarada jako/bin/sh
powłoki.#!/bin/sh
jest zwykle tylko linkiem, ponieważ powłoka Bourne'a nie jest już utrzymywana. W wielu systemach Unix/bin/sh
będzie link do/bin/ksh
lub/bin/ash
na wielu systemach Linux RHEL oparte będzie to link/bin/bash
, jednak na Ubuntu i wielu systemów opartych na Debianie jest to link/bin/dash
. Wszystkie powłoki, wywołane jakosh
, wejdą w tryb zgodności z POSIX.Hashbang jest jednak ważnym symbolem zastępczym, ponieważ pozwala na znacznie większą przenośność niż inne metody, pod warunkiem, że twój skrypt jest ściśle zgodny z POSIX (co podkreśla znaczenie).
Uwaga: Gdy
bash
zostanie wywołany w trybie POSIX, nadal będzie dopuszczał niektóre rzeczy inne niż POSIX, takie jak[[
tablice i inne. Te rzeczy mogą zawieść w niesystemiebash
.źródło
/bin/ash
.#! /
zamiast po prostu#!
.Masz to zacofane.
/bin/sh
w dzisiejszych czasach prawie nigdy nie jest powłoką Bourne'a i właśnie wtedy masz problem z używaniem She#! /bin/sh
-Bang.Powłoka Bourne'a była powłoką napisaną pod koniec lat 70. i zastąpiła poprzednią powłokę Thompson (zwaną także
sh
). Na początku lat 80. David Korn napisał kilka rozszerzeń dla powłoki Bourne'a, naprawił kilka błędów i powodował problemy z projektowaniem (i wprowadził kilka) i nazwał ją skorupą Korna.Na początku lat 90. POSIX określił
sh
język w oparciu o podzbiór powłoki Korn, a większość systemów obecnie zmieniła swój język na/bin/sh
powłokę Korn lub powłokę zgodną z tą specyfikacją. W przypadku BSD stopniowo zmieniali/bin/sh
początkowo (po tym, jak nie mogli już używać powłoki Bourne'a ze względów licencyjnych) powłokę Almquist, klon powłoki Bourne'a z niektórymi rozszerzeniami ksh, więc stała się zgodna z POSIX.Obecnie wszystkie systemy POSIX mają powłokę o nazwie
sh
(najczęściej, ale niekoniecznie w/bin
, POSIX nie określa ścieżki określonych przez nią narzędzi), która jest w większości zgodna z POSIX. Zasadniczo jest oparty na ksh88, ksh93, pdksh, bash, ash lub zsh², ale nie na powłoce Bourne'a, ponieważ powłoka Bourne'a nigdy nie była zgodna z POSIX3. Niektóre z tych skorup (bash
,zsh
,yash
i niektórepdksh
pochodne włączenia trybu do POSIX przy wywołaniu jaksh
i są mniej zgodne inaczej).bash
(odpowiedź GNU na powłokę Korna) jest w rzeczywistości jedyną powłoką typu open source (i można powiedzieć, że obecnie jest utrzymywana, ponieważ inne są generalnie oparte na ksh88, który nie otrzymał żadnej nowej funkcji od lat 90.), który został certyfikowany jako zgodność z POSIXsh
(jako część certyfikacji macOS).Kiedy piszesz skrypt za pomocą
#! /bin/sh -
she-bang, powinieneś użyć standardowejsh
składni (i powinieneś również użyć standardowej składni narzędzi używanych w tym skrypcie, jeśli chcesz być przenośny, to nie tylko powłoka jest zaangażowana podczas interpretacji powłoki skrypt), to nie ma znaczenia, jaka implementacja tego standardowegosh
interpretera składni jest używana (ksh
,bash
...).Nie ma znaczenia, że te powłoki mają rozszerzenia ponad standard, o ile ich nie używasz. To tak, jakby pisać kod C, o ile piszesz standardowy kod C i nie używasz rozszerzeń jednego kompilatora (podobnego
gcc
) lub drugiego, kod powinien kompilować się OK bez względu na implementację kompilatora, pod warunkiem, że kompilator jest zgodny.Tutaj z
#! /bin/sh
she-bang, głównym problemem byłyby systemy, w których/bin/sh
jest Bourne shell, że na przykład nie obsługuje standardowe funkcje, takie jak$((1+1))
,$(cmd)
,${var#pattern}
... W takim przypadku konieczne może być obejścia takich jak:Nawiasem mówiąc, Ubuntu
/bin/sh
niebash
jest domyślnie. Obecnie jestdash
to powłoka oparta na NetBSDsh
, sama oparta na powłoce Almquist, która jest w większości zgodna z POSIX, z wyjątkiem tego, że nie obsługuje znaków wielobajtowych. W Ubuntu i innych systemach opartych na Debianie możesz wybierać pomiędzybash
idash
za/bin/sh
pomocą 4dpkg-reconfigure dash
) . skrypty dostarczane z Debianem powinny działać tak samo w obu powłokach, ponieważ są zapisane w standardzie polityki Debiana (nadzbiór standardu POSIX). Prawdopodobnie znajdziesz również pracować OK „s emulacji lub (prawdopodobnie nie , ani które nie mają polecenie wbudowane (wymagane przez politykę Debiana ale nie POSIX)).sh
zsh
sh
bosh
ksh93
yash
local
Wszystkie systemy w unix.stackexchange.com mają
sh
gdzieś POSIX . Większość z nich ma/bin/sh
(możesz znaleźć bardzo rzadkie, które nie mają/bin
katalogu, ale prawdopodobnie nie przejmujesz się tym), i na ogół jest tosh
interpreter POSIX (aw rzadkich przypadkach (niestandardowa) powłoka Bourne'a ).Ale
sh
jest to jedyny plik wykonywalny interpretera powłoki, który z pewnością znajdziesz w systemie. W przypadku innych powłok możesz być pewien, że będą miały macOS, Cygwin i większość dystrybucji GNU / Linuxbash
. Systemy operacyjne wywodzące się z SYSV (Solaris, AIX ...) zazwyczaj mają ksh88, prawdopodobnie ksh93. OpenBSD, MirOS będzie miał pochodną pdksh. macOS będzie miałzsh
. Ale z tego nie będzie żadnej gwarancji. Nie ma gwarancji, żebash
ani żadna z tych innych powłok nie zostanie zainstalowana w/bin
innym miejscu (zwykle znajduje się/usr/local/bin
na BSD, gdy jest instalowana). I oczywiście nie ma gwarancji wersji powłoki, która zostanie zainstalowana.Zauważ, że
#! /path/to/executable
nie jest to konwencja , jest to cecha wszystkich jąder uniksopodobnych ( wprowadzonych na początku lat 80. przez Dennisa Ritchiego ), która umożliwia wykonywanie dowolnych plików poprzez określenie ścieżki interpretera w pierwszym wierszu, zaczynając od#!
. Może to być dowolny plik wykonywalny.Po uruchomieniu pliku, którego pierwsza linia rozpoczyna się
#! /some/file some-optional-arg
jądro kończy się wykonaniem/some/file
zsome-optional-arg
, ścieżki skryptu i oryginalnych argumentów jako argumenty. Możesz zrobić ten pierwszy wiersz,#! /bin/echo test
aby zobaczyć, co się dzieje:Kiedy używasz
/bin/sh -
zamiast/bin/echo test
, jądro wykonuje/bin/sh - ./myscript foo
,sh
interpretuje kod zawartości zapisany w nimmyscript
i ignoruje ten pierwszy wiersz jako komentarz (zaczyna się od#
).¹ Prawdopodobnie jedynym obecnie systemem, w którym ktokolwiek z nas natknie się na system
/bin/sh
oparty na powłoce Bourne'a, jest Solaris 10. Solaris jest jednym z niewielu uników, które zdecydowały się zachować tam powłokę Bourne'a ze względu na kompatybilność wsteczną (sh
język POSIX nie jest w pełni wstecznie kompatybilny z powłoką Bourne'a) i (przynajmniej dla wdrożeń na komputery stacjonarne i pełne serwery) mają POSIXsh
gdzie indziej (w/usr/xpg4/bin/sh
, na podstawie ksh88), ale zmieniło się to w Solarisie 11, gdzie/bin/sh
jest teraz ksh93. Pozostałe są w większości nieczynne.² MacOS / X stosowany się , a później zmieniła się . Używanie go jako implementacji POSIX nie jest głównym celem . Jego trybem jest przede wszystkim możliwość osadzania lub wywoływania ( ) kodu POSIX w skryptach
/bin/sh
zsh
bash
zsh
sh
sh
source
sh
zsh
³ Ostatnio @schily rozszerzył powłokę OpenSolaris (bazującą na powłoce SVR4, opartą na powłoce Bourne'a), aby stała się zgodna z POSIX,
bosh
ale nie wiem, czy jest ona używana w żadnym systemie. Dziękiksh88
temu jest to druga powłoka zgodna z POSIX, oparta na kodzie powłoki Bourne'a4 W starszych wersjach można również użyć
mksh
lub jego większejlksh
inkarnacji POSIX . To jest powłoka MirOS (wcześniej MirBSD) oparta na pdksh, sama oparta na powłoce Forsyth (kolejna reimplementacja powłoki Bourne))źródło
exec sh "$0" "$@"
po ustawieniuPATH
? To powinno odebraćsh
z właściwego miejsca, pomyślałem.$PATH
.$(...)
tryby emacs / vi, rozszerzenia tyldy / nawiasów klamrowych (te początkowo z csh), fc, skład, alias , składnia funkcji w stylu ksh ...Tak, możesz użyć
#!/bin/sh
w skrypcie, ponieważ/bin/sh
jest (mam nadzieję) przewidziany w takich systemach, zwykle za pośrednictwem linku, który sprawia, żebash
zachowujesz się (mniej więcej) tak, jaksh
by to zrobił. Oto na przykład system Centos7, który prowadzish
dobash
:Możesz także użyć,
#!/bin/bash
jeśli piszeszbash
skrypt tylko dla tego systemu i chcesz korzystać zbash
funkcji. Jednak takie skrypty będą miały problemy z przenośnością, na przykład na OpenBSD, gdziebash
jest instalowany tylko wtedy, gdy administrator z trudem go zainstaluje (nie robię), a następnie jest instalowany/usr/local/bin/bash
, a nie/bin/bash
.#!/bin/sh
Skrypt ściśle POSIX powinien być bardziej przenośny.źródło
sh
, Bash przechodzi do trybu POSIX po odczytaniu plików startowych.” - gnu.org/software/bash/manual/bashref.html#Bash-POSIX-Mode#!/bin/bash
dokładnie, aby móc korzystać z funkcji innych niż POSIX./bin/sh
to dowiązanie symbolicznebash
, czy to prawda? Ale wiem na pewno o CentOS.bash
. Plik binarny wie, jaką nazwę użyto do wywołania go, a kiedy się nazywash
, działa jak oldschoolowy Bournesh
.Zapytałeś
Odpowiedź zależy od tego, co napiszesz w skrypcie powłoki.
Jeśli ściśle używasz przenośnych skryptów zgodnych z POSIX i nie używasz żadnych poleceń specyficznych dla bash, możesz tego użyć
/bin/sh
.Jeśli wiesz, że kiedykolwiek używasz skryptu tylko na maszynie z bash i chcesz użyć składni specyficznej dla bash, powinieneś użyć
/bin/bash
Jeśli chcesz mieć pewność, że skrypt będzie działał na asortymencie maszyn unixowych, powinieneś używać tylko składni zgodnej z POSIX, i
/bin/sh
Jeśli regularnie używać innej powłoki (np ksh , zsh lub tcsh ), a chcesz używać tej składni w skrypcie, to należy użyć odpowiedniego tłumacza (jak
/bin/ksh93
,/bin/zsh
lub/bin/tcsh
)źródło
„#!” komentarz nie zawsze używa
/bin/bash
lub/bin/sh
. Podaje tylko, czym powinien być interpreter, nie tylko w przypadku skryptów powłoki. Na przykład moje skrypty python zwykle zaczynają się od#!/usr/bin/env python
.Teraz różnica między
#!/bin/sh
i#!/bin/bash
jest taka, że/bin/sh
nie zawsze jest to dowiązanie symboliczne/bin/bash
. Często, ale nie zawsze. Ubuntu jest tutaj godnym uwagi wyjątkiem. Widziałem skrypty działające poprawnie na CentOS, ale nie działające na Ubuntu, ponieważ autor używał składni specyficznej dla bash#!/bin/sh
.źródło
Przepraszamy za nalewanie zimnej wody wszystkim wspaniałym odpowiedziom, które mówią, że
/bin/sh
jest obecny we wszystkich systemach uniksowych - jest obecny, z wyjątkiem najczęściej używanego systemu Unix wszechczasów: Androida.Android ma swoją powłokę
/system/bin/sh
i zwykle nie ma możliwości utworzenia/bin/sh
łącza, nawet w systemie zrootowanym (z powodu sposobu, w jaki system jest zablokowany za pomocą zestawów ograniczających selinux i zdolności (7)).Dla tych, którzy powiedzą, że Android nie jest zgodny z POSIX: nie ma też większości dystrybucji Linuksa i BSD. A istnienie
/bin/sh
tej ścieżki nie jest wymagane przez standard :źródło
getconf
? Na przykład w systemie Solaris 11.4/usr/bin
? Jeden w/usr/xpg4/bin
(dla zgodności z SUSv2), Jeden w/usr/xpg6/bin
(dla zgodności z SUSv3)?/usr/xpg7/bin
(dla SUSv4)?/bin/sh