Gibt es einen Grund, warum ein Shebang auf / bin / sh anstatt auf / bin / bash zeigt?

53

In den meisten Shell-Skripten, die ich gesehen habe (außer denen, die ich selbst nicht geschrieben habe), ist mir aufgefallen, dass der Shebang auf eingestellt ist #!/bin/sh. Das überrascht mich nicht wirklich bei älteren Skripten, aber es gibt es auch bei relativ neuen Skripten.

Gibt es einen Grund für die Bevorzugung /bin/shüber /bin/bash, da so bashziemlich allgegenwärtig ist, und oft standardmäßig auf vielen Linux und BSD Maschinen gehen zurück mehr als ein Jahrzehnt?

Jules
quelle
23
Es ist eine gute Sache, /bin/shwenn Sie keine bestimmten bashFunktionen verwenden. Eines Tages könnte es sein, dass Sie eines Ihrer Skripte auf einem System verwenden müssen, auf dem es nicht installiert ist (Remote-Server, eingebetteter Computer ...)
Mathieu
1
im allgemeinen sollte man es vermeiden, fragen zu stellen, die sich aufgrund der meinung beantworten lassen (das ist meines erachtens die einzig mögliche art und weise, wie diese frage beantwortet werden kann - aber das ist nur meine meinung ) .
mikeserv
9
Ich glaube, dass es möglich ist, diese Frage ohne bloße Meinung zu beantworten, indem auf mindestens zwei Organisationen verwiesen wird, die sich über mehrere Jahre mit genau dieser Sache befasst haben, und die Geschichte und das Ergebnis betrachtet werden. Mit viel weiterer Lektüre, um zu booten. ☺
JdeBP
3
@JulesMazur ...the answers so far are fairly subjective...Eine "subjektive" Aussage ist per Definition im Wesentlichen meinungsbasiert. /bin/bashsollte nur verwendet werden, wenn bash ausdrücklich benötigt wird. In über 40 Jahren als Entwickler habe bashich es lange zuvor fast nie ausdrücklich gebraucht, außer beim Testen. (Ich bemühe mich auch, Shell-Erweiterungen zu vermeiden, aber die meisten meiner Skripte sind für die Verteilung bestimmt.) Viele Skripte im Netz sollten auch für eine breite Verwendung gedacht sein.
user2338816
2
@ user2338816 mein schlechtes meinte ich objektiv . Vielen Dank für Ihre Punkte!
Jules

Antworten:

83
  1. Es gibt Systeme, die standardmäßig keine Bash liefern (z. B. FreeBSD).
  2. Auch wenn bash installiert ist, befindet es sich möglicherweise nicht in /bin.
  3. Die meisten einfachen Skripte erfordern keine Bash.
  4. Die Verwendung der POSIX-Shell ist portabler und die Skripte können auf einer größeren Anzahl von Systemen ausgeführt werden.
Marco
quelle
17
Ein weiterer Grund: Oft ist / bin / sh schneller als bash oder lädt zumindest schneller (weil es kleiner ist).
Derobert
5
@derobert, /bin/shist schneller, wenn nicht bash, gibt es noch ein paar Systeme wie OS / X oder RHEL, wo es /bin/shist bash.
Stéphane Chazelas
1
Nein. Einige Betriebssysteme verknüpfen es, da bash abwärtskompatibel ist.
Sobrique
7
Nicht wenige Skripte gehen davon aus, dass dies der Fall /bin/shist /bin/bash. Ubuntu, das von bash zu dash wechselte, hat sie alle kaputt gemacht.
Atamanroman
19
@atamanroman: Die Skripte waren an erster Stelle falsch, sie hätten verwendet werden sollen, #!/bin/bashwenn sie Bash wollten (daran ist nichts auszusetzen!). Die Änderung wurde größtenteils in Debian durchgeführt. Es verbesserte die Benutzererfahrung und hatte messbare Auswirkungen auf die Startzeit des Systems. Es wirkt sich auch positiv auf die Sicherheit aus, siehe "Shellshock".
Dietrich Epp
28

Die meisten Systemskripte in Linux (mit Debian-Bezug: Ubuntu, Mint usw.) sind so geschrieben, dass sie in dem schnelleren Strich ausgeführt werden können, der in diesen Systemen die Standardeinstellung / bin / sh ist. Der Grund ist zweifach:

  • Geschwindigkeit des Systems. Ein kleinerer Strichcode wird schneller geladen und auch schneller ausgeführt. Mit einigem (kleinen?) Zusätzlichen Aufwand (Kosten) für Programmierer von Shell-Skripten.

  • Sicherheit. Die Vielfalt der Muscheln trägt zur Widerstandsfähigkeit gegen Bugs bei. Debian-Systeme waren größtenteils nicht anfällig für Shellshock, da die Standard-Shell keine solche Anfälligkeit aufwies.

Bash ist in der Tat die Standard-Shell für Benutzer , da sie leistungsfähiger ist und viel mehr Elemente enthält, die das Codieren erleichtern. Dies ist auch die Standardeinstellung shin Mac OS (diejenige, die mit / bin / sh verknüpft ist). Der Aufruf bashmit dem shLinknamen von startet jedoch als posix-kompatible Shell.


quelle
2
Ein begrenzterer Satz verfügbarer Werkzeuge einer einfacheren Shell erschwert das Schreiben von Code (bitte vermeiden Sie einen fanatischen Krieg). Aus diesem Grund mögen einige Benutzer zsh, das noch mehr Tools als bash zur Verfügung hat. Ich mag Bash mehr als eine Balance zwischen beiden Extremen.
4
@RobertL, viele der in ksh hinzugefügten und von bash übernommenen Funktionen sind vorhanden, da sie das Schreiben robuster und korrekter Skripte erheblich vereinfachen. Ohne die verschiedenen Zusätze, mit denen die indirekte Zuordnung und Auswertung sicher durchgeführt werden kann, kann man sich beispielsweise evalmit der damit verbundenen Sicherheitsanfälligkeit befassen. In ähnlicher Weise kann es ohne eingebaute Regex-Unterstützung erforderlich sein, externe Befehle (mit einem hohen Leistungsnachteil) für den Abgleich auch innerhalb einer einzelnen Zeile usw. zu verwenden.
Charles Duffy
1
@RuiFRibeiro, in Debian ist nichts statisch verknüpft. Dash ist eingeschränkter, aber hauptsächlich in interaktiven Funktionen (keine Vervollständigung und so weiter), so dass es für Skripte schneller ist.
Jan Hudec
21

Andere haben darauf hingewiesen, dass die Prämissen der Frage, dass die Bourne Again-Shell standardmäßig und allgegenwärtig ist, völlig falsch sind.

Darüber hinaus gibt es in der Tat gute Gründe, etwas anderes als die Bourne Again-Shell für die Interpretation von Shell-Skripten zu verwenden. Diese Gründe Ubuntu und Debian großes Projekt, über eine Reihe von Jahren motiviert, bashisms zu entfernen und so viele der Shell - Skripte ausführen , indem der Systeminitialisierung (die eine war , um viel von Shell - Skripten mit System 5 rc) und Paket Installation / Deinstallation verwenden die Debian Almquist-Shell anstelle der Bourne Again-Shell.

Einfach ausgedrückt: Die Bourne Again-Shell ist nicht der schnellste Shell-Interpreter für ein POSIX-konformes Shell-Skript. Wenn man also seine Shellskripte POSIX-konform machen kann, indem man sie mit einem leichteren Programm wie der Debian Almquist-Shell interpretiert, wird das System eine bessere Leistung bringen. (Am Ende musste Debian geringfügige Anpassungen an der Almquist-Shell vornehmen, um einige Nicht-POSIX-Shell-Konstrukte zu unterstützen, die einfach zu tief und weit eingebettet und zu nützlich waren, um sie loszuwerden.)

Das Ergebnis war ein deutlicher Anstieg der Bootstrap-Leistung.

Es sind also zwei verschiedene Klassen von Shell zu betrachten:

  • Die Shells mit allen auffälligen interaktiven Funktionen, die als interaktive Anmeldeshells für Benutzer in der Kontodatenbank konfiguriert sind .
  • Die Shells, die viele Skripte schnell interpretieren und von Shell-Skriptprogrammen als Skriptinterpreter verwendet werden.

Beachten Sie, dass es zu einfach ist, dies als "Bevorzugen /bin/sh" zu bezeichnen. Debian hatte tatsächlich mindestens zwei Ziele:

  1. Gegenüber Administratoren, die die Debian Almquist-Shell, die Z-Shell (im POSIX-Modus), die Bourne Again-Shell (im POSIX-Modus), die MirBSD Korn-Shell und andere verwenden /bin/sh, gab es entweder ...

    1. … Die Skripte so portabel wie möglich zu gestalten, damit das Umstellen der zugeordneten /bin/shElemente keine Probleme verursacht; oder

    2. … Dass nicht portierbare Skripte explizit auf das richtige Interpreterprogramm abzielen , anstatt nur diese /bin/shZuordnung zu erwarten .

  2. Es wurde die Debian Almquist-Shell /bin/shanstelle der Bourne-Shell als Standardzuordnung festgelegt , so dass diejenigen Skripte, die POSIX-konform (oder genauer gesagt, Debian Policy Manual-konform) waren, schneller ausgeführt wurden.

Und wenn man sich einmal damit befasst, kann man natürlich noch viel weiter gehen. wie die Effizienz Kompromisse wie /bin/trueund /usr/bin/clearals Shell-Skripte oder kompilierte Programme zu berücksichtigen . Aber das geht zum Glück über den Rahmen dieser Antwort hinaus. ☺

Nichts davon ist sehr neu, und natürlich nicht einmal Unix-spezifisch. Vor der Jahrhundertwende habe ich einen Befehlszeileninterpreter geschrieben und veröffentlicht, der sowohl in "interaktiven" als auch in "nicht interaktiven" Varianten verfügbar war. Dabei wurde genau diese Unterteilung in der Dokumentation erläutert und der Unterschied zwischen den Variablen COMSPECund der OS2_SHELLUmgebungsvariablen festgestellt . Ebenso geht die Diskussion über das Entfernen von Bashismen in Debians System V rcund über das Installieren / Entfernen von Paketen auf die neunziger Jahre zurück.

Weitere Lektüre

JdeBP
quelle
2
"Am Ende musste Debian die Almquist-Shell geringfügig anpassen, um einige Nicht-POSIX-Shell-Konstrukte zu unterstützen, die einfach zu tief und weit eingebettet und zu nützlich waren, um sie loszuwerden." - Welcher Ihrer vielen Links hat Informationen dazu? Das hört sich sehr interessant an. :)
Wildcard
3
IMHO ist Leistung nur ein Motivator, um Leute zu veranlassen, mit den änderungen übereinzustimmen. Der erste große Grund für die Änderung war, dass Bash die Abwärtskompatibilität immer wieder unterbrach. Ich persönlich musste mindestens dreimal in meiner Karriere Bash-Probleme beheben, da das Skript in einer Version von Bash funktionierte, in einer anderen jedoch fehlschlug (normalerweise nach einem Betriebssystem-Upgrade). Dash ist nicht nur ein etwas schnellerer Dolmetscher. Es ist auch viel stabiler in Bezug auf das Verhalten.
Slebetman
Es würde mich interessieren, ob die Kommentare in der Schily Bourne ShellManpage unter schilytools.sourceforge.net/bosh.html geeignet sind, den Leuten zu ermöglichen, zu verstehen, wie man ein portables Skript schreibt (das hängt nur von Bourne Shell featuresab 1989 ab). Was ich tat, war, jede Verbesserung zu erwähnen, die nicht in alten Bourne Shells war. Übrigens: Ich bin auch daran interessiert, eine Liste von Bashismen in Strichen zu kennen.
Schily
8

Gibt es einen Grund, warum ein Shebang auf / bin / sh anstatt auf / bin / bash zeigt?

Ja. @Marcos ausgezeichnete Antwort umreißt dies gut.

Was soll ich in meinem Shebang verwenden?

Wenn Sie Ihre eigenen Skripte schreiben, sollten Sie den Shebang auf die allgemeinste Sache richten, gegen die Sie getestet haben.

Ist auf meinem System (Centos 6.6) shverknüpft mit bash:

$ ls -l /bin/sh 
lrwxrwxrwx 1 root root 4 Dec  2  2014 /bin/sh -> bash

Dies bedeutet, dass ich immer #!/bin/bashin meinem Shebang verwende, es sei denn, ich habe überprüft, dass mein Skript keine Bashims enthält.

Indem Sie den shebang auf #!/bin/shSie setzen, versprechen Sie, dass das Skript mit allen Implementierungen von funktioniert sh.

Dies ist ein viel größeres Versprechen, als zu sagen, dass das Skript mit bash funktioniert.

Hier ist ein Beispiel für ein Skript, das sich abhängig von shder vom System verwendeten Implementierung falsch verhält :

#!/bin/sh
n=1
a=$((++n))
echo $n

Bei Verwendung bashdes Skripts wird gedruckt:

2

Bei Verwendung dashdes Skripts wird gedruckt:

1

Wenn ich verwenden möchte, #!/bin/shwas muss ich tun?

  • Überprüfen Sie das Skript mit checkbashisms- Beachten Sie, dass nicht alle Bashims gefunden werden. Ich habe den Bashismus oben in meinem Drehbuch nicht gefunden
  • Testen Sie das Skript mit einer anderen shImplementierung. Ich dashteste normalerweise mit , erwarte jedoch, dass einige Bashismen oder Dashims noch durchrutschen können.

Die DashAsBinSh-Seite im Ubuntu-Wiki enthält viele interessante Informationen.

Sixtyfootersdude
quelle
6
Msgstr "Wenn Sie Ihre eigenen Skripte schreiben, sollten Sie den shebang auf das allgemeinste zeigen, gegen das Sie getestet haben. Wenn Sie den shebang auf #! / Bin / sh setzen, versprechen Sie, dass das Skript mit allen Implementierungen von sh funktioniert . " Hervorragender Punkt. +1, und du hast mich umdenken lassen, wie ich meine shebangs für die Zukunft schreiben werde. Danke! :)
Wildcard
2
Nun, nicht alle Implementierungen von /bin/sh; nur die POSIX-konformen.
Blacklight Shining
4

Der einzige verbleibende Grund, ein Shell-Skript anstelle eines Skripts in einer leistungsfähigeren und ergonomischeren Sprache zu schreiben, besteht darin, dass die Portabilität auf Legacy-Systeme mit unbekannter installierter Software wichtiger ist als jeder andere Faktor .

/bin/shist der einzige Skript-Interpreter, der für alles verfügbar ist, was sich Unix nennt. Aber auf einer Menge älterer Systeme /bin/shund den damit verbundenen Dienstprogrammen ist die POSIX.1-1996-Spezifikation für "Shell und Dienstprogramme" nicht einmal konform, geschweige denn modernere. Standardkonforme Tools sind ein optionales Add-On, das an /usr/xpg4einem solchen nicht offensichtlichen Ort installiert wird . 1 Das Schreiben von Skripten in die Portable-Subset-Shell-Sprache ist noch mühsamer und fehleranfälliger als das Schreiben von Skripten in die POSIX-Shell-Sprache. (Lesen Sie ein von Autoconf erstelltes configureSkript einmal durch, wenn Sie mir nicht glauben. Nur das Setup sollte ausreichen, um Sie zu überzeugen.)

Wenn Sie jedoch davon ausgehen können, dass ein anderer Skriptinterpreter installiert ist (z. B. Bash), können Sie davon ausgehen, dass ein Interpreter für eine bessere Skriptsprache installiert ist. Perl zum Beispiel ist mit größerer Wahrscheinlichkeit verfügbar als Bash.

Deshalb sollten Sie niemals ein #! /bin/bashSkript schreiben , denn wenn dies eine Option ist, ist auch eine bessere Sprache eine Option.

1 Zum Beispiel haben Solaris 10 und älter die ursprüngliche Bourne-Shell als ausgeliefert /bin/sh. Ich wurde informiert, dass Solaris 11 es auf ksh93 aktualisiert hat.

zwol
quelle
3
In welcher Sprache schreiben Sie ein Skript, um ein System zu booten? Oder in einem SOHO-Router (eingeschränkte Einbettungssysteme)? Oder in Android? In all diesen Fällen steht eine Shell zur Verfügung. Perl nicht.
1
Es gibt einige Ungenauigkeiten in Bezug auf die Solaris-bezogenen Teile Ihrer Antwort. Unter Solaris 10 und älter /bin/shhandelt es sich nicht um POSIX.1-1996, sondern um eine ursprüngliche Bourne-Shell vor POSIX-Syntax. Das macht #!/bin/shdie Ausführung von Skripten mit diesen Releases zu einem sehr schlechten Erlebnis. Portable Skripte unter Solaris werden verwendet, #!/usr/xpg4/bin/shdie unter anderen Betriebssystemen nicht sehr portabel sind. Auf dem neuesten Solaris, Oracle Solaris 11 veröffentlicht 2011 erste, /bin/shist ein modernes , ksh93die mit den letzten POSIX - Spezifikationen erfüllt, und viele moderne Erweiterungen hat.
Juli
1
@BinaryZebra: "Eine Shell" wird verfügbar sein, ja. Aber bash ist nicht unbedingt die Shell (insbesondere die meisten SOHO-Router, ashdie mit busybox geliefert werden), und ich glaube, zwol hat recht, dass Perl häufiger verfügbar ist als bash.
Ben Voigt
1
@BenVoigt Ich kommentiere diesen Satz "Der einzige verbleibende Grund, ein Shell-Skript zu schreiben". Es gibt immer noch einige Instanzen, die für einige Aufgaben eine Shell benötigen (nicht für alle). Das waren einige Beispiele aus meinem Kopf. OTOH In Systemen mit genügend Arbeitsspeicher (fast alle in heutigen Standards) und genügend Leistung ist die Installation von Perl (oder Python oder ...) recht schnell und einfach. Ich plädiere jedoch nicht für eine bestimmte Shell. Wo liest du das in meinem Kommentar?
2
Stimmen bashSie in keiner Weise mit Ihrer hochmeinenden und nicht sachlichen Behauptung überein, dass "wenn verfügbar, dann ist dies eine bessere Sprache, so dass Sie niemals bashCode schreiben sollten ". Außerdem sollten Sie, wie @sixtyfootersdude betont, immer verwenden, es #!/bin/bashsei denn, Sie haben getestet, dass Ihr Skript mit einer POSIX-Shell funktioniert.
Wildcard
0

Sie sollten entweder tatsächlich verwenden

#! /bin/env sh

oder

#! /bin/env bash

Auf diese Weise rufen Sie eine der Shells auf, je nachdem, wie sie auf diesem System installiert sind.

Verwenden Sie zur Erhöhung der Sicherheit ( z. B. bei Neustarts durch Einzelbenutzer) eine shandere Verwendung bash.

Paul Evans
quelle
6
Aus dieser Antwort : the advantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH. The disadvantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH.Dies gilt wahrscheinlich auch für shund bash.
Jules
12
Nein, Sie sollten #!/bin/envin einem portablen Skript nichts verwenden. Man kann durchaus davon ausgehen, dass /bin/shes eine funktionsfähige, POSIX-kompatible Shell gibt. Andererseits hat keines meiner Systeme eine /bin/env.
Blacklight Shining
Auch ein guter Punkt.
Jules
1
@Blacklight Shining Es ist definitiv falsch, eine POSIX-kompatible Shell anzunehmen /bin/sh. Für POSIX ist dies nicht erforderlich. Stattdessen werden andere Regeln definiert, um eine POSIX-kompatible Umgebung auf einer POSIX-zertifizierten Plattform zu erhalten.
Schily
4
/usr/bin/envist nicht allgemein verfügbar ...
vonbrand