Du hast es verkehrt herum. /bin/sh
ist heutzutage fast nie mehr eine Bourne-Muschel, und es ist dann, wenn Sie ein Problem haben, wenn Sie einen She #! /bin/sh
-Bang verwenden.
Die Bourne-Shell war eine Shell, die Ende der 70er Jahre geschrieben wurde und die vorherige Thompson-Shell (auch als "Shell" bezeichnet sh
) ersetzte . In den frühen 80er Jahren hat David Korn einige Erweiterungen für die Bourne-Shell geschrieben, einige Fehler behoben und Ungeschicklichkeiten im Design behoben (und einige eingeführt) und sie als Korn-Shell bezeichnet.
In den frühen 90er Jahren spezifizierte POSIX die sh
Sprache basierend auf einer Teilmenge der Korn-Shell, und die meisten Systeme haben ihre Sprache jetzt /bin/sh
entweder in die Korn-Shell oder in eine Shell geändert , die dieser Spezifikation entspricht. Bei BSDs änderten sie schrittweise /bin/sh
die Almquist-Shell (nachdem sie die Bourne-Shell aus Lizenzgründen nicht mehr verwenden konnten), einen Klon der Bourne-Shell mit einigen ksh-Erweiterungen, sodass sie POSIX-kompatibel wurde.
Heutzutage haben alle POSIX-Systeme eine Shell, die POSIX-kompatibel ist sh
(meistens, aber nicht unbedingt /bin
, gibt POSIX nicht den Pfad der angegebenen Dienstprogramme an). Es basiert im Allgemeinen entweder auf ksh88, ksh93, pdksh, bash, ash oder zsh², jedoch nicht auf der Bourne-Shell, da die Bourne-Shell niemals POSIX-kompatibel war³. Ein paar dieser Schalen ( bash
, zsh
, yash
und einige pdksh
Derivate ermöglichen eine POSIX-kompatiblen Modus , wenn aufgerufen , wie sh
und sind weniger konform auf andere Weise).
bash
(die GNU-Antwort auf die Korn-Shell) ist tatsächlich die einzige Open-Source-Shell (und man könnte sagen, dass sie derzeit nur gewartet wird, da die anderen in der Regel auf ksh88 basieren, das seit den 90er Jahren keine neuen Funktionen mehr hat), die als zertifiziert wurde POSIX-konform sein sh
(im Rahmen der macOS-Zertifizierung).
Wenn Sie ein Skript mit einem #! /bin/sh -
She-Bang schreiben , sollten Sie eine Standardsyntax verwenden sh
(und auch Standardsyntax für die in diesem Skript verwendeten Dienstprogramme verwenden, wenn Sie portabel sein möchten. Es ist nicht nur die Shell, die bei der Interpretation einer Shell beteiligt ist Skript), dann spielt es keine Rolle, welche Implementierung dieses Standard- sh
Syntax-Interpreters verwendet wird ( ksh
, bash
...).
Es spielt keine Rolle, dass diese Shells Erweiterungen über dem Standard haben, solange Sie sie nicht verwenden. Es ist wie beim Schreiben von C-Code. Solange Sie Standard-C-Code schreiben und keine Erweiterungen des einen gcc
oder anderen Compilers verwenden , sollte der Code unabhängig von der Compilerimplementierung einwandfrei kompiliert werden, sofern der Compiler kompatibel ist.
Hier mit dem #! /bin/sh
sie Bang, Ihr Hauptproblem wäre die Systeme, in denen /bin/sh
ist die Bourne - Shell , dass zum Beispiel nicht unterstützt Standard - Features wie $((1+1))
, $(cmd)
, ${var#pattern}
... , in dem Fall , dass Sie Umgehungen benötigen wie:
#! /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
Übrigens ist Ubuntu /bin/sh
nicht bash
standardmäßig. Es ist dash
heutzutage eine Shell, die auf NetBSD basiert sh
, selbst auf der Almquist-Shell, die größtenteils POSIX-kompatibel ist, außer dass sie keine Multi-Byte-Zeichen unterstützt. Auf Ubuntu und andere Debian-basierten Systemen können Sie wählen zwischen bash
und dash
für /bin/sh
mit dpkg-reconfigure dash
) 4 . sh
Mit Debian gelieferte Skripte sollten in beiden Shells genauso funktionieren, wie sie nach dem Debian-Richtlinienstandard (einer Obermenge des POSIX-Standards) geschrieben wurden. Sie werden wahrscheinlich feststellen, dass sie auch in zsh
der sh
Emulation funktionieren oder bosh
(wahrscheinlich nicht ksh93
oder yash
nicht mit local
eingebautem Code (erforderlich für die Debian-Richtlinie, aber nicht für POSIX)).
Alle Systeme im Geltungsbereich von unix.stackexchange.com haben sh
irgendwo eine POSIX . Die meisten von ihnen haben eine /bin/sh
(Sie finden vielleicht sehr seltene, die kein /bin
Verzeichnis haben, aber das interessiert Sie wahrscheinlich nicht), und das ist im Allgemeinen ein POSIX- sh
Interpreter (und in seltenen Fällen eine (nicht standardmäßige) Bourne-Shell) ).
Aber sh
ist der einzige ausführbare Shell-Interpreter, den Sie auf einem System finden können? Für die anderen Shells können Sie sicher sein, dass macOS, Cygwin und die meisten GNU / Linux-Distributionen installiert sind bash
. Von SYSV abgeleitete Betriebssysteme (Solaris, AIX ...) haben im Allgemeinen ksh88, möglicherweise ksh93. OpenBSD, MirOS wird ein pdksh-Derivat haben. MacOS wird haben zsh
. Aber davon gibt es keine Garantie. Es kann weder garantiert werden, ob bash
noch eine dieser anderen Shells in /bin
oder an einem anderen Ort installiert wird (dies ist beispielsweise bei /usr/local/bin
BSD-Installationen normalerweise der Fall). Und natürlich keine Garantie für die Version der Shell, die installiert wird.
Beachten Sie, dass dies #! /path/to/executable
keine Konvention ist , sondern eine Funktion aller Unix-ähnlichen Kernel ( eingeführt in den frühen 80ern von Dennis Ritchie ), mit der beliebige Dateien ausgeführt werden können, indem der Pfad des Interpreters in einer ersten Zeile beginnend mit angegeben wird #!
. Es kann sich um eine beliebige ausführbare Datei handeln.
Wenn Sie eine Datei mit der ersten Zeile beginnt , deren ausführen #! /some/file some-optional-arg
, beendet der Kernel - Ausführung nach oben /some/file
mit some-optional-arg
, dem Pfad des Skripts und die ursprünglichen Argumente als Argumente. Sie können diese erste Zeile machen, um #! /bin/echo test
zu sehen, was passiert:
$ ./myscript foo
test ./myscript foo
Wenn Sie /bin/sh -
anstelle von verwenden /bin/echo test
, wird der Kernel ausgeführt /bin/sh - ./myscript foo
, sh
der in gespeicherte Inhaltscode interpretiert myscript
und die erste Zeile als Kommentar ignoriert (beginnt mit #
).
¹ Wahrscheinlich /bin/sh
ist Solaris 10 das einzige System, auf dem heutzutage jeder von uns auf ein System stößt, das auf der Bourne-Shell basiert. Solaris ist eines der wenigen Unices, die sich aus Gründen der Abwärtskompatibilität dafür entschieden haben, eine Bourne-Shell dort zu belassen (die POSIX- sh
Sprache ist nicht vollständig) Abwärtskompatibel mit der Bourne-Shell) und (zumindest für Desktop- und vollständige Server-Bereitstellungen) haben POSIX an sh
anderer Stelle (in /usr/xpg4/bin/sh
, basierend auf ksh88), aber das hat sich in Solaris 11 geändert, wo /bin/sh
jetzt ksh93 ist. Die anderen sind meistens verstorben.
² Das /bin/sh
von MacOS / X war früher,zsh
wurde aber später auf geändert bash
. Es ist nicht zsh
das Hauptaugenmerk, als POSIX- sh
Implementierung verwendet zu werden. Der sh
Modus besteht hauptsächlich darin, source
POSIX- sh
Code in zsh
Skripte einbetten oder aufrufen zu können
³ Vor kurzem hat @schily die OpenSolaris-Shell (basierend auf der SVR4-Shell, basierend auf der Bourne-Shell) so erweitert, dass sie POSIX-kompatibel ist. bosh
Mir ist jedoch noch nicht bekannt, dass sie auf einem beliebigen System verwendet wird. Zusammen ksh88
damit ist es eine zweite POSIX-kompatible Shell, die auf dem Code der Bourne-Shell basiert
4 In älteren Versionen können Sie auch mksh
POSIX verwenden lksh
. Das ist die MirOS-Shell (ehemals MirBSD), die auf pdksh basiert, selbst basiert auf der Forsyth-Shell (eine weitere Neuimplementierung der Bourne-Shell).