Ich habe gesehen, dass der Ausdruck „sh-kompatibel“ normalerweise in Bezug auf Shells verwendet wird. Ich bin mir nicht sicher, ob es auch für Programme gilt, die von Shells aus ausgeführt werden können.
Was bedeutet es, wenn eine Shell oder ein anderes Programm „sh-kompatibel“ ist? Was würde es bedeuten, „sh inkompatibel“ zu sein?
Bearbeiten:
Diese Frage, die den Unterschied zwischen bash und sh stellt, ist sehr relevant:
Unterschied zwischen sh und bash
Ich hätte immer noch gerne eine direkte Antwort darauf, was es bedeutet, „sh-kompatibel“ zu sein. Eine vernünftige Erwartung könnte sein, dass „sh-kompatibel“ bedeutet „implementiert die Shell-Befehlssprache“, aber warum gibt es dann so viele „sh-kompatible“ Shells und warum unterscheiden sie sich?
Akzeptierte Antwort:
Warum gibt es so viele „sh-kompatible“ Shells?
Die Bourne-Shell wurde erstmals 1979 als Teil von Unix V7 veröffentlicht. Da so ziemlich jedes Unix und Unix-ähnliche System von V7 Unix abstammt – und sei es auch nur in geistiger Hinsicht – hat uns die Bourne-Shell „für immer“ begleitet¹
Die Bourne-Shell ersetzte tatsächlich eine frühere Shell, die als Thompson-Shell bezeichnet wurde, aber sie geschah so früh in der Geschichte von Unix, dass sie heute so gut wie vergessen ist. Die Bourne-Schale ist eine Obermenge der Thompson-Schale.²
Sowohl die Bourne- als auch die Thompson-Shell hießen sh
. Die von POSIX spezifizierte Shell wird auch sh
genannt . Also, wenn jemand sh
sagt -kompatibel, beziehen sie sich handwinkend auf diese Muschelserie. Wenn sie es genau wissen wollten, würden sie „POSIX-Shell“ oder „Bourne-Shell“ sagen.³
Die POSIX-Shell basiert auf der Version von KornShell von 1988, die ihrerseits die Bourne-Shell auf AT&T Unix ersetzen sollte und die BSD-C-Shell in Bezug auf Funktionen überholte.⁴ Soweit ksh
der Vorfahre der POSIX-Shell ist, enthalten die meisten Unix- und Unix-ähnlichen Systeme heute eine Variante der Korn-Shell. Ausnahmen sind im Allgemeinen winzige eingebettete Systeme, die sich nicht den Platz leisten können, den eine vollständige POSIX-Shell einnimmt.
Abgesehen davon wurde die Korn-Shell – als etwas, das sich von der POSIX-Shell unterscheidet – außerhalb der kommerziellen Unix-Welt nie wirklich populär. Dies liegt daran, dass sein Aufstieg mit den frühen Jahren der Unix-Kommerzialisierung korrespondierte, sodass es in die Unix-Kriege verwickelt wurde. BSD-Unixes verzichteten darauf zugunsten der C-Shell, und ihr Quellcode war zu Beginn nicht frei für die Verwendung in Linux verfügbar.⁵ Als die frühen Linux-Distributoren also nach einer Befehlsshell suchten, die zu ihrem Linux-Kernel passte, suchten sie Sie wählten normalerweise GNU Bash, eines dieser sh
-kompatibel, von denen Sie sprechen.⁶
Diese frühe Assoziation zwischen Linux und Bash besiegelte so ziemlich das Schicksal vieler anderer Shells, einschließlich ksh
, csh
und tcsh
. Es gibt auch heute noch Hartgesottene, die diese Muscheln verwenden, aber sie sind sehr in der Minderheit.⁷
All diese Geschichte erklärt, warum die Schöpfer von relativen Nachzüglern wie bash
, zsh
, und yash
entschied sich dafür, sie sh
zu machen -kompatibel:Bourne/POSIX-Kompatibilität ist das Minimum, das eine Shell für Unix-ähnliche Systeme bieten muss, um weit verbreitet zu sein.
In vielen Systemen die standardmäßige interaktive Befehlsshell und /bin/sh
sind verschiedene Dinge. /bin/sh
kann sein:
-
Die ursprüngliche Bourne-Shell. Dies ist bei älteren UNIX®-Systemen wie Solaris 10 (veröffentlicht 2005) und seinen Vorgängern üblich.⁸
-
Eine POSIX-zertifizierte Shell. Dies ist bei neueren UNIX®-Systemen wie Solaris 11 (2010) üblich.
-
Die Almquist-Muschel . Dies ist ein Open-Source-Bourne/POSIX-Shell-Klon, der ursprünglich 1989 im Usenet veröffentlicht wurde und dann zu Berkeleys CSRG zur Aufnahme in die erste BSD-Veröffentlichung beigetragen wurde, die keinen AT&T-Quellcode enthält, 4.4BSD-Lite. Die Almquist-Shell wird oft als
ash
bezeichnet , auch wenn es als/bin/sh
installiert ist .4.4BSD-Lite wiederum wurde mit
/bin/sh
zur Basis für alle modernen BSD-Derivate bleibt in den meisten von ihnen ein Almquist-Derivat, mit einer großen Ausnahme, die unten erwähnt wird. Sie können diese direkte Nachkommenschaft in den Quellcode-Repositories für NetBSD und FreeBSD sehen:Sie haben vom ersten Tag an ein Almquist-Shell-Derivat ausgeliefert.Es gibt zwei wichtige
ash
Forks außerhalb der BSD-Welt:-
dash
, bekanntermaßen 2006 von Debian und Ubuntu als Standard/bin/sh
übernommen Implementierung. (Bash bleibt die standardmäßige interaktive Befehlsshell in Debian-Derivaten.) -
Die
ash
Befehl in BusyBox, der häufig in eingebetteten Linuxen verwendet wird und zum Implementieren von/bin/sh
verwendet werden kann . Da esdash
nachdatiert und es wurde von Debians altemash
abgeleitet Paket habe ich mich entschieden, es als Ableitung vondash
zu betrachten stattash
, trotz seines Befehlsnamens innerhalb von BusyBox.(BusyBox enthält auch eine weniger funktionsreiche Alternative zu
ash
genannthush
. Typischerweise wird nur einer der beiden in eine gegebene BusyBox-Binärdatei eingebaut:ash
standardmäßig, aberhush
wenn der Platz wirklich eng ist. Also/bin/sh
auf BusyBox-basierten Systemen ist nicht immerdash
-ähnlich.)
-
-
GNU Bash , das die meisten seiner Nicht-POSIX-Erweiterungen deaktiviert, wenn es als
sh
aufgerufen wird .Diese Auswahl ist typisch für Desktop- und Server-Varianten von Linux, mit Ausnahme von Debian und seinen Derivaten. Mac OS X hat dies auch seit Panther getan, das 2003 veröffentlicht wurde.
-
Eine Shell mit
ksh93
POSIX-Erweiterungen , wie bei OpenBSD. Obwohl die OpenBSD-Shell ihr Verhalten ändert, um syntaktische und semantische Inkompatibilitäten mit Bourne- und POSIX-Shells zu vermeiden, wenn sie alssh
aufgerufen wird , es deaktiviert keine seiner reinen Erweiterungen, da es sich nicht um solche handelt, die nicht mit älteren Shells in Konflikt geraten.Dies ist nicht üblich; Sie sollten
ksh93
nicht erwarten Funktionen in/bin/sh
.
Ich habe „Shell-Skript“ oben als Oberbegriff für Bourne/POSIX-Shell-Skripting verwendet. Dies liegt an der Allgegenwart von Muscheln der Bourne-Familie. Um über Skripting auf anderen Shells zu sprechen, müssen Sie einen Qualifizierer wie „C-Shell-Skript“ angeben. Selbst auf Systemen, auf denen eine Shell der C-Familie die standardmäßige interaktive Shell ist, ist es besser, die Bourne-Shell für das Skripting zu verwenden.
Es ist bezeichnend, dass Wikipedia, wenn es Unix-Shells klassifiziert, sie in Bourne-Shell-kompatibel, C-Shell-kompatibel und „Andere“ gruppiert.
Verwandte:Benutzerfreundlicher Befehl zum Auflisten aller Benutzer auf dem Ubuntu-System?Dieses Diagramm kann helfen:
(Klicken Sie hier, um die SVG-Version, 31 kB, oder die PNG-Version in voller Größe, 218 kB, anzuzeigen.)
Was würde es bedeuten, „sh inkompatibel“ zu sein?
Jemand spricht über ein sh
-inkompatibles Ding bedeutet normalerweise eines von drei Dingen:
-
Sie beziehen sich auf eine dieser „anderen“ Shells.⁹
-
Sie unterscheiden zwischen den Bourne- und C-Shell-Familien.
-
Sie sprechen über ein bestimmtes Feature in einer Shell der Bourne-Familie, das nicht in allen anderen Shells der Bourne-Familie vorhanden ist.
ksh93
,bash
undzsh
haben insbesondere viele Funktionen, die in den älteren „Standard“-Shells nicht vorhanden sind. Diese drei sind auch in vielerlei Hinsicht nicht kompatibel, sobald Sie über das gemeinsame POSIX/ksh88
hinauskommen Basis.
Es ist ein klassischer Fehler, ein Shell-Skript mit einem #!/bin/sh
zu schreiben shebang-Zeile oben, aber um Bash- oder Korn-Shell-Erweiterungen darin zu verwenden. Seit /bin/sh
ist eine der Shells im Diagramm der Korn/POSIX-Familie oben auf so vielen Systemen heutzutage, dass solche Skripte auf dem System funktionieren, auf dem sie geschrieben wurden, aber dann auf Systemen fehlschlagen, auf denen /bin/sh
ist etwas aus der breiteren Familie der Bourne-Muscheln. Best Practice ist die Verwendung von #!/bin/bash
oder #!/bin/ksh
Shebang-Zeilen, wenn das Skript solche Erweiterungen verwendet.
Es gibt viele Möglichkeiten zu prüfen, ob ein bestimmtes Shell-Skript der Bourne-Familie portierbar ist:
-
Führen Sie
checkbashisms
aus darauf, ein Tool aus dem Debian-Projekt, das ein Skript auf „Bashismen“ prüft. -
Führen Sie es unter
posh
aus , eine Shell im Debian-Paket-Repository, die absichtlich nur von SUS3 spezifizierte Features implementiert, plus ein paar andere kleinere Features. -
Führen Sie es unter
obosh
aus aus dem Schily Tools-Projekt, eine verbesserte Version der Bourne-Shell als Open Source von Sun als Teil von OpenSolaris im Jahr 2005, was es zu einer der einfachsten Möglichkeiten macht, eine Bourne-Shell im Stil von 1979 auf einem modernen Computer zu installieren.Die Schily Tools-Distribution enthält auch
bosh
, eine Shell vom Typ POSIX mit vielen nicht standardmäßigen Funktionen, die jedoch nützlich sein kann, um die Kompatibilität von Shell-Skripten zu testen, die auf allen Shells der POSIX-Familie ausgeführt werden sollen. Es ist tendenziell konservativer in seinem Feature-Set alsbash
,zsh
und die erweiterten Versionen vonksh93
.Schily Tools enthält auch eine Shell namens
bsh
, aber das ist eine historische Kuriosität, die überhaupt kein Gehäuse der Bourne-Familie ist. -
Lesen Sie das Kapitel Portable Shell Programming im GNU Autoconf-Handbuch. Vielleicht erkennen Sie einige der problematischen Konstrukte, über die es in Ihren Skripten spricht.
Warum sind sie unterschiedlich?
Aus den gleichen Gründen sind alle „Neu &Verbessert!“ Dinge sind anders:
-
Die verbesserte Version konnte nur verbessert werden, indem die Abwärtskompatibilität gebrochen wurde.
-
Jemand hat sich eine andere Art und Weise ausgedacht, wie etwas funktionieren könnte, was ihnen besser gefällt, aber das ist nicht die gleiche Art und Weise, wie die alte funktioniert hat.
-
Jemand hat versucht, einen alten Standard neu zu implementieren, ohne ihn vollständig zu verstehen, also hat er es vermasselt und einen unbeabsichtigten Unterschied geschaffen.
Fußnoten und Randbemerkungen :
-
Frühe Versionen von BSD Unix waren nur Add-On-Softwaresammlungen für V6 Unix. Da die Bourne-Shell erst in V7 zu AT&T Unix hinzugefügt wurde, hatte BSD technisch gesehen nicht mit der Bourne-Shell begonnen. BSDs Antwort auf die primitive Natur der Thompson-Shell war die C-Shell.
Trotzdem basierten die ersten Standalone-Versionen von BSD (2.9BSD und 3BSD) auf V7 oder seinem portablen Nachfolger UNIX/32V, also hatten sie es die Bourne-Shell enthalten.
(Die 2BSD-Reihe wurde zu einer parallelen Abzweigung von BSD für Digitals PDP-Minicomputer, während die 3BSD- und 4BSD-Reihen fortfuhren, neuere Computertypen wie Vaxen- und Unix-Workstations zu nutzen. 2.9BSD war im Wesentlichen die PDP-Version von 4.1cBSD; das waren sie gleichzeitiger und geteilter Code. PDPs verschwanden nicht einfach, als die VAX ankam, also watschelt die 2BSD-Linie immer noch dahin.)
Man kann mit Sicherheit sagen, dass die Bourne-Shell 1983 überall in der Unix-Welt war. Das ist eine gute Annäherung an „für immer“ in der Computerindustrie. MS-DOS bekam in diesem Jahr ein hierarchisches Dateisystem (aww, wie süß!) und den ersten 24-Bit-Macintosh mit seinem 9-Zoll-B&W-Bildschirm – nicht Graustufen, buchstäblich schwarz und weiß – würde erst Anfang nächsten Jahres herauskommen.
-
Die Thompson-Schale war nach heutigen Maßstäben ziemlich primitiv. Es war nur eine interaktive Befehlsshell und nicht die Skript-Programmierumgebung, die wir heute erwarten. Es hatte Dinge wie Pipes und E/A-Umleitung, die wir als prototypischen Teil einer „Unix-Shell“ betrachten, sodass wir davon ausgehen, dass die MS-DOS-Befehlsshell sie von Unix erhält.
Die Bourne-Shell ersetzte auch die PWB-Shell, die der Thompson-Shell wichtige Dinge wie Programmierbarkeit hinzufügte (
if
,switch
undwhile
) und eine frühe Form von Umgebungsvariablen. Die PWB-Shell ist noch weniger in Erinnerung als die Thompson-Shell, da sie nicht Teil jeder Unix-Version war. -
Wenn jemand nicht ist speziell in Bezug auf die Kompatibilität von POSIX und Bourne-Shell gibt es eine ganze Reihe von Dingen, die sie bedeuten könnten.
Auf der einen Seite könnten sie die Bourne-Shell von 1979 als Basis verwenden. Ein „
sh
-kompatibles Skript“ in diesem Sinne bedeuten, dass es perfekt auf der echten Bourne-Shell oder einem ihrer Nachfolger und Klone laufen soll:ash
,bash
,ksh
,zsh
usw.Jemand am anderen Extrem nimmt stattdessen die von POSIX angegebene Shell als Basislinie an. Wir nehmen heutzutage so viele Funktionen der POSIX-Shell als „Standard“, dass wir oft vergessen, dass sie in der Bourne-Shell eigentlich nicht vorhanden waren:eingebaute Arithmetik, Jobsteuerung, Befehlshistorie, Aliase, Befehlszeilenbearbeitung, der
$()
Form der Befehlsersetzung usw. -
Obwohl die Wurzeln der Korn-Shell bis in die frühen 1980er Jahre zurückreichen, hat AT&T sie erst mit System V Release 4 im Jahr 1988 in Unix ausgeliefert. Da so viele kommerzielle Unixe auf SVR4 basieren, wurde hier
ksh
gesetzt in so ziemlich jedem relevanten kommerziellen Unix seit den späten 1980er Jahren.(Ein paar seltsame Unix-Varianten, die auf SVR3 und früher basierten, hielten sich nach der Veröffentlichung von SVR4 am Markt fest, aber sie waren die ersten, die gegen die Wand drängten, als die Revolution kam.)
1988 ist auch das Jahr, in dem der erste POSIX-Standard mit seiner Korn-Shell-basierten „POSIX-Shell“ herauskam. Später, im Jahr 1993, kam eine verbesserte Version der Korn-Shell heraus. Da POSIX das Original effektiv an Ort und Stelle genagelt hat,
ksh
in zwei Hauptversionen aufgeteilt:ksh88
undksh93
, benannt nach den Jahren ihrer Trennung.ksh88
ist nicht vollständig POSIX-kompatibel, obwohl die Unterschiede gering sind, sodass einige Versionen desksh88
Shell wurden gepatcht, um POSIX-kompatibel zu sein. (Dies aus einem interessanten Interview auf Slashdot mit Dr. David G. Korn. Ja, der Typ, der die Shell geschrieben hat.)ksh93
ist eine voll kompatible Obermenge der POSIX-Shell. Entwicklung aufksh93
ist sporadisch aufgetreten, seit das primäre Quell-Repository von AT&T zu GitHub verschoben wurde, wobei die neueste Version etwa 3 Jahre alt ist, während ich dies schreibe, ksh93v. (Der Basisname des Projekts bleibtksh93
mit hinzugefügten Suffixen, um Release-Versionen nach 1993 zu kennzeichnen.)Systeme, die eine Korn-Shell getrennt von der POSIX-Shell enthalten, stellen sie normalerweise als
/bin/ksh
zur Verfügung , obwohl es sich manchmal woanders versteckt.Wenn wir über
ksh
sprechen oder Korn-Shell namentlich sprechen wir vonksh93
Merkmale, die es von seinen abwärtskompatiblen Bourne- und POSIX-Shell-Subsets unterscheiden. Auf den reinenksh88
stößt man selten heute. -
AT&T hielt den Quellcode der Korn-Shell bis März 2000 proprietär. Zu diesem Zeitpunkt war die Verbindung von Linux mit GNU Bash sehr stark. Bash und
ksh93
jeder hat Vorteile gegenüber dem anderen, aber an diesem Punkt hält die Trägheit Linux fest mit Bash verbunden.Warum die frühen Linux-Anbieter am häufigsten GNU Bash gegenüber
pdksh
wählen , was war zu der Zeit, als Linux anfing, verfügbar war, schätze ich, weil so viel vom restlichen Userland auch aus dem GNU-Projekt stammte. Bash ist auch etwas fortgeschrittener alspdksh
, da sich die Bash-Entwickler nicht darauf beschränken, Funktionen der Korn-Shell zu kopieren.Arbeite an
pdksh
hörte etwa zu der Zeit auf, als AT&T den Quellcode für die echte Korn-Shell veröffentlichte. Es gibt jedoch zwei Hauptzweige, die noch gepflegt werden:der OpenBSDpdksh
und die MirBSD-Korn-Shell,mksh
.Ich finde es interessant, dass
mksh
ist die einzige derzeit für Cygwin gepackte Korn-Shell-Implementierung. -
GNU Bash geht in vielerlei Hinsicht über POSIX hinaus, aber Sie können es bitten, in einem reineren POSIX-Modus zu laufen.
-
csh
/tcsh
war in den frühen 1990er Jahren normalerweise die interaktive Standard-Shell auf BSD-Unixen.Da es sich um eine BSD-Variante handelte, waren frühe Versionen von Mac OS X bis Mac OS X 10.2 „Jaguar“ so. OS X hat die Standard-Shell von
tcsh
geändert Bash in OS X 10.3 „Panther“. Diese Änderung wirkte sich nicht auf Systeme aus, die von 10.2 oder früher aktualisiert wurden. Die bestehenden Benutzer auf diesen konvertierten Systemen behielten ihrentcsh
Schale.FreeBSD behauptet, immer noch
tcsh
zu verwenden als Standard-Shell, aber auf der FreeBSD 10-VM, die ich hier habe, scheint die Standard-Shell eine der POSIX-kompatiblen Almquist-Shell-Varianten zu sein. Dies gilt auch für NetBSD.OpenBSD verwendet einen Fork von
pdksh
stattdessen als Standard-Shell.Die höhere Popularität von Linux und OS X lässt einige Leute wünschen, dass FreeBSD auch auf Bash umsteigen würde, aber sie werden dies aus philosophischen Gründen in absehbarer Zeit nicht tun. Es ist einfach zu wechseln, wenn Sie das stört.
-
Es ist selten, ein System mit einer wirklich einfachen Bourne-Shell als
/bin/sh
zu finden heutzutage. Sie müssen sich die Mühe machen, etwas zu finden, das ihm für Kompatibilitätstests ausreichend nahe kommt.Mir ist nur eine Möglichkeit bekannt, eine echte Vintage-Bourne-Shell von 1979 auf einem modernen Computer auszuführen:Verwenden Sie die Ancient Unix V7-Disk-Images mit dem SIMH PDP-11-Simulator aus dem Computer History Simulation Project. SIMH läuft auf so ziemlich jedem modernen Computer, nicht nur auf Unix-ähnlichen. SIMH läuft sogar auf Android und auf iOS.
Mit OpenSolaris hat Sun erstmals die SVR4-Version der Bourne-Shell veröffentlicht. Davor war der Quellcode für die Post-V7-Versionen der Bourne-Shell nur für Benutzer mit einer Unix-Quellcodelizenz verfügbar.
Dieser Code ist jetzt separat vom Rest des nicht mehr existierenden OpenSolaris-Projekts aus verschiedenen Quellen verfügbar.
Die direkteste Quelle ist das Shell-Projekt Heirloom Bourne. Diese wurde kurz nach der ursprünglichen Veröffentlichung von OpenSolaris im Jahr 2005 verfügbar. In den nächsten Monaten wurden einige Portabilitäts- und Fehlerbehebungsarbeiten durchgeführt, aber dann wurde die Entwicklung des Projekts gestoppt.
Jörg Schilling hat eine bessere Arbeit geleistet, eine Version dieses Codes als
obosh
zu pflegen in seinem Schily Tools Paket. Siehe oben für mehr dazu.Denken Sie daran, dass diese Shells, die von der Quellcode-Veröffentlichung von 2005 abgeleitet wurden, Unterstützung für Multibyte-Zeichensätze, Jobsteuerung, Shell-Funktionen und andere Funktionen enthalten, die in der ursprünglichen Bourne-Shell von 1979 nicht vorhanden waren.
Eine Möglichkeit, festzustellen, ob Sie sich auf einer originalen Bourne-Shell befinden, besteht darin, zu prüfen, ob sie ein undokumentiertes Feature unterstützt, das hinzugefügt wurde, um den Übergang von der Thompson-Shell zu erleichtern:
^
als Alias für|
. Das heißt, ein Befehl wiels ^ more
gibt auf einer Korn- oder POSIX-Shell einen Fehler aus, verhält sich aber wiels | more
auf einer echten Bourne-Shell. -
Gelegentlich begegnen Sie einem
fish
,scsh
oderrc/es
Anhänger, aber sie sind noch seltener als C-Shell-Fans.Der
rc
Familie von Shells wird auf Unix/Linux-Systemen nicht häufig verwendet, aber die Familie ist historisch wichtig, weshalb sie sich einen Platz im obigen Diagramm verdient hat.rc
ist die Standard-Shell des Betriebssystems Plan 9 von Bell Labs, eine Art Nachfolger der 10. Ausgabe von Unix, das als Teil der kontinuierlichen Forschung von Bell Labs zum Betriebssystemdesign entwickelt wurde. Es ist auf Programmierebene sowohl mit Bourne als auch mit der C-Shell inkompatibel; Da ist wahrscheinlich eine Lektion drin.Die aktivste Variante von
rc
scheint das von Toby Goodwin gepflegte zu sein, das auf Unixrc
basiert Klon von Byron Rakitzis.