Jaka jest różnica między #! / Bin / sh i #! / Bin / bash?

280

jeśli napiszę

#!/bin/bash
echo "foo"

lub

#!/bin/sh
echo "foo"

oba dają takie same. Widziałem niektóre skrypty zaczynające się od #!/bin/shlub #!/bin/bash. Czy jest jakaś różnica między nimi?

Rahul Virpara
źródło

Odpowiedzi:

242

bashi shsą dwiema różnymi powłokami. Zasadniczo bashjest sh, z większą liczbą funkcji i lepszą składnią. Większość poleceń działa tak samo, ale są różne.

Powiedziawszy to, powinieneś zdać sobie sprawę, że /bin/shna większości systemów będzie dowiązanie symboliczne i nie będzie wywoływać sh. W Ubuntu zwykło /bin/shsię łączyć z bashtypowym zachowaniem w dystrybucjach Linuksa, ale teraz zmieniło się na łączenie z inną powłoką o nazwie dash . Użyłbym bash, ponieważ jest to w zasadzie standard (lub przynajmniej najczęstszy, z mojego doświadczenia). W rzeczywistości pojawiają się problemy, gdy użyje skryptu bash, #!/bin/shponieważ twórca skryptu zakłada, że ​​link jest, bashgdy nie musi.

Aby uzyskać więcej informacji, http://man.cx/sh , http://man.cx/bash .

reverendj1
źródło
24
Twój pierwszy akapit jest dość mylący. „sh” wcale nie jest powłoką, ale dowiązaniem symbolicznym do obecnie skonfigurowanej powłoki systemowej , którą w systemach Linux jest zwykle albo bash, albo dash (ostatnie wersje Ubuntu używające tej ostatniej).
thomasrutter
18
/bin/shKiedyś była powłoką o nazwie Bourne Shell w 1977 roku. Bash jest powłoką kompatybilną z / bin / sh, która może być używana jako zamiennik Bourne'a, który jest zgodny z POSIX-em. en.wikipedia.org/wiki/Bourne_shell
Alex
5
bash jest de facto standardem (bardzo szeroko stosowanym), ale nie jest „standardem”; sh na Ubuntu używa dash , który jest powłoką zgodną z Posix, więc jest to naprawdę standard. Radzę używać myślnika tak często, jak to możliwe do skryptów, szczególnie w przypadku skryptów po stronie serwera. Chociaż bash jest bardziej wyrazisty, myślnik działa znacznie szybciej i jest bezpieczniejszy.
Rick-777,
@ Rick-777 Czy powinienem więc wyraźnie umieścić #! / Bin / dash na górze moich skryptów? Napisałem również skrypty, w których piszę tylko polecenia i wykonuję je przy użyciu ./scriptName i to działa dobrze. Czy konieczne jest #! / Bin / yourShellHere?
user137717,
@ Rick-777 W przypadkach, w których wykluczam dowolne #! / Bin / shellName, nazwałem pliki fileName.sh. Czy będzie to domyślnie link do preferowanej powłoki systemu bez deklarowania #! / Bin / sh?
user137717,
82

W systemie Linux i innych systemach uniksowych masz do wyboru wiele powłok.

Powłoka jest odpowiedzialna nie tylko za rysowanie twojego małego podpowiedzi, ale także za interpretację twoich poleceń, szczególnie jeśli używasz skomplikowanej logiki, takiej jak potoki, warunki warunkowe i tak dalej.

bash jest najpopularniejszą powłoką używaną jako domyślna powłoka dla użytkowników systemów Linux. Jest duchowym potomkiem innych powłok używanych w historii Unixa. Jego nazwa, bash jest skrótem od Bourne-Again Shell, hołdem dla powłoki Bourne'a, którą zaprojektowano w celu jej zastąpienia, chociaż zawiera ona również cechy z Shell C i Shell Korn.

Obecnie działa od /bin/bash- każdy system z bash będzie miał tutaj dostęp.

Jednak nie tylko użytkownicy używają powłok. Skrypty ( skrypty powłoki ) potrzebują powłok do ich interpretacji. Po uruchomieniu skryptu powłoki system musi uruchomić proces powłoki, aby wykonać skrypt.

Problem polega na tym, że różne powłoki mają między sobą niewielkie niespójności, a jeśli chodzi o uruchamianie skryptów, mogą to być prawdziwy problem. bash ma całkiem sporo funkcji skryptowych, które są unikalne tylko dla bash, a nie dla innych powłok. To dobrze, jeśli zawsze zamierzasz używać bash do uruchamiania tych skryptów. Inne powłoki mogą próbować emulować bash lub stosować się do standardu POSIX, który bash obsługuje całkiem dobrze (choć dodaje własne rozszerzenia).

Możliwe jest określenie na górze skryptu powłoki, która powłoka powinna być uruchamiana za pomocą shebang. Skrypt może określać #!/bin/bashw pierwszym wierszu, co oznacza, że ​​skrypt powinien zawsze być uruchamiany za pomocą bash, a nie innej powłoki.

/ bin / sh to plik wykonywalny reprezentujący powłokę systemową . W rzeczywistości jest zwykle implementowany jako dowiązanie symboliczne wskazujące plik wykonywalny dla dowolnej powłoki powłoki systemowej. Powłoka systemowa jest rodzajem domyślnej powłoki, której powinny używać skrypty systemowe. W dystrybucji Linuksa przez długi czas był to zwykle symboliczny link do basha , do tego stopnia, że ​​stała się konwencją, aby zawsze link / bin / sh do basha lub powłoki kompatybilnej z bash. Jednak w ciągu ostatnich kilku lat Debian (i Ubuntu) postanowił zmienić powłokę systemową z bash na dash- podobna powłoka - zrywająca z długą tradycją w Linuksie (cóż, GNU) używania bash dla / bin / sh. Dash jest postrzegany jako lżejsza i znacznie szybsza powłoka, która może być korzystna dla szybkości rozruchu (i innych rzeczy, które wymagają wielu skryptów powłoki, takich jak skrypty instalacyjne pakietów).

Dash jest dość dobrze kompatybilny z bash, oparty na tym samym standardzie POSIX. Jednak nie implementuje rozszerzeń specyficznych dla bash. Istnieją skrypty, które używają #!/bin/sh(powłoki systemowej) jako shebang, ale które wymagają rozszerzeń specyficznych dla bash. Obecnie jest to uważane za błąd, który powinien naprawić Debian i Ubuntu, którzy wymagają / bin / sh, aby móc działać po wskazaniu kreski.

Mimo że powłoka systemowa Ubuntu wskazuje na myślnik, twoja powłoka logowania jako użytkownik nadal jest bash. Oznacza to, że gdy zalogujesz się do emulatora terminala w dowolnym miejscu w systemie Linux, twoja powłoka logowania będzie bash. Szybkość działania nie stanowi większego problemu, gdy powłoka jest używana interaktywnie, a użytkownicy znają bash (i mogą mieć specyficzne dla bash dostosowania w swoim katalogu domowym).

Czego należy używać podczas pisania skryptów

Jeśli twój skrypt wymaga funkcji obsługiwanych tylko przez bash, użyj #!/bin/bash.

Ale jeśli to w ogóle możliwe, dobrze jest upewnić się, że skrypt jest zgodny z POSIX i używać #!/bin/sh, co zawsze, całkiem niezawodnie, wskazuje na preferowaną powłokę systemową zgodną z POSIX w każdej instalacji.

thomasrutter
źródło
18

Oprócz poprzednich odpowiedzi, nawet jeśli /bin/shjest dowiązaniem symbolicznym /bin/bash, #!/bin/shnie jest całkowicie równoważne z #!/bin/bash.

Ze strony podręcznika bash (1) :

„Jeśli bash jest wywoływany z nazwą sh, próbuje naśladować zachowanie startowe historycznych wersji sh tak dokładnie, jak to możliwe, przy jednoczesnym zachowaniu zgodności ze standardem POSIX.”

Na przykład składnia specyficzna dla bash:

 exec  > >(tee logfile.txt)

daje błąd w powłoce zaczynającej się od #!/bin/sh, nawet z założonym łączem symbolicznym sh-> bash.

AnkiF
źródło
6

GNU Bash: #!/bin/bash; POSIX powłoki: #!/bin/sh.

山 茶树 和 葡萄 树
źródło
Krótka, ale dokładna odpowiedź. 还 行
Sergiy Kolodyazhnyy