Verwenden Sie #! / Bin / sh oder #! / Bin / bash, um Ubuntu-OSX-Kompatibilität, Benutzerfreundlichkeit und POSIX zu gewährleisten

18

Ich weiß, dass ich beide als erste Zeile von Skripten verwenden kann, um die gewünschte Shell aufzurufen.

Wäre #!/bin/shzu empfehlen, wenn Kompatibilität mit allen Unix-Systemen unabdingbar ist?

In meinem Fall interessieren mich nur Ubuntu (Debian) und OSX. Könnte ich #!/bin/bashdavon ausgehen, dass es auf beiden Systemen funktioniert?
Würde dies auch die Verwendung von Skripten mit einer moderneren und klareren Syntax für Befehle erleichtern? Bezieht sich using #!/bin/shauch auf POSIX?

Michael Durrant
quelle
1
Wahrscheinlich erwähnenswert, dass viele Distributionen zusammengelegt haben /binund /usr/bin. Aus diesem Grund ist es #!/usr/bin/env <shname>heutzutage wahrscheinlich besser, es für die Portabilität zu verwenden .
HalosGhost

Antworten:

15

Wenn Sie für den Anfang davon ausgehen können, dass Bash vorinstalliert ist (was meines Wissens auf allen von Ihnen aufgelisteten Systemen der Fall ist), verwenden Sie den folgenden Hashbang, um kompatibel zu sein:

#!/usr/bin/env bash

Dies ruft alles auf, was bashgerade konfiguriert wird, egal ob es sich in /binoder befindet /usr/local/bin.

Auf den meisten Systemen eines breiten Spektrums (einschließlich AIX, Solaris und verschiedenen BSD-Versionen) bashlandeten sie an verschiedenen Standorten, jedoch envimmer in /usr/bin/env. Der Trick liegt jedoch nicht bei mir, sondern beim Autor des Bash Cookbook.

Wie auch immer, mit Bash können Sie einige "moderne" Funktionen verwenden, die Ihnen das Leben erleichtern.

Zum Beispiel die doppelten Klammern:

[[ -f "/etc/debian_version" ]] && echo "This is a Debian flavor"

In traditionellen Shell-Dialekten müsste man auf Folgendes zurückgreifen:

test -f "/etc/debian_version" && echo "This is a Debian flavor"

Das Beste an den doppelten Klammern ist jedoch, dass sie reguläre Ausdrücke für den Abgleich zulassen. Das Bash Hackers Wiki gibt Ihnen viele Tricks in diese Richtung.

Sie können auch ganz bequeme Ausdrücke wie $((2**10))oder andere arithmetische Ausdrücke verwenden, die der $((expression))Syntax entsprechen.

Die Verwendung von Backticks für Subshells ist in Ordnung, wenn auch etwas veraltet. Die Verschachtelungsfunktionen von $(command ...)Aufrufen sind jedoch viel praktischer, da Sie nicht viele Dinge auf verschiedenen Subshell-Ebenen umgehen müssen.

Dies sind nur ein paar Dinge, die Bash Ihnen gegenüber der herkömmlichen POSIX- shSyntax bietet .

Aber wenn Sie mehr Leistung auf der Shell wollen (nicht nur in Skripten), schauen Sie sich auch an zsh.

0xC0000022L
quelle
Bash ist ein sehr nützliches Tool, aber achten Sie darauf, es nicht zum Starten von Diensten zu verwenden, die für einen Bash- Skriptfehler anfällig sind, z . B. access.redhat.com/security/cve/CVE-2014-6271 . Halten Sie sich an shsolche Aufgaben.
Rick-777
1
Rick-777, dass die Sicherheitslücke weitestgehend überwunden war und ich denke, dass Ihr Kommentar FUD ist. Wenn ein Systemdienst unter bash ausgeführt wird, ist er in keiner Weise für diesen Fehler anfällig. Es ist nur dann für diesen Fehler anfällig, wenn es einen Bash-Prozess abbricht und Remotebenutzern direkten Zugriff auf eine oder mehrere Umgebungsvariablen wie in FastCGI ermöglicht, und selbst dann nur auf nicht gepatchten Versionen von Bash. Auf Systemen mit einer shVerknüpfung zu bashwird die Sicherheitsanfälligkeit nicht durch die Verwendung von verringert sh.
Score_Under
11

In Debian und Ubuntu /bin/shist dashdies eine POSIX-kompatible Shell. Wenn Sie dies angeben #!/bin/sh, müssen Sie sich in Ihrem Skript auf POSIX-Anweisungen beschränken. (Der Vorteil ist, dass der dashStart schneller erfolgt als bash, sodass Ihr Skript seine Arbeit in kürzerer Zeit erledigen kann.)

Auf vielen (den meisten?) Anderen Linux-Systemen /bin/shist dies bashder Grund, warum viele Skripte mit #!/bin/shihrer Shebang-Zeile geschrieben werden, obwohl sie bashErweiterungen verwenden.

Wenn Sie bashErweiterungen verwenden möchten , ist es am sichersten, diese auf allen Systemen anzugeben #!/bin/bash. Auf diese Weise geben Sie ausdrücklich Ihre Abhängigkeit von an bash. Sie müssen dies unter Debian und Ubuntu tun. Als zusätzlichen Bonus werden beim Start /bin/sh basheinige Erweiterungen deaktiviert ( Details finden Sie in der Beschreibung des bashPOSIX-Modus ). Daher #!/bin/bashist eine genaue Angabe erforderlich, damit Sie den vollen Nutzen daraus ziehen können bash.

Unter OS X /bin/bashist auch verfügbar und /bin/shist bash. Die Angabe #!/bin/bashfunktioniert auch dort.

Stephen Kitt
quelle
5

Ja, sowohl OSX als auch Linux werden mitgeliefert /bin/bash. Sie sollten absolut sicher sein. Dies ist jedoch kein POSIX. Die POSIX-Shell /bin/shfunktioniert auf den meisten (allen?) Systemen. Dies ist der portabelste Ansatz und die einzige Möglichkeit, POSIX-kompatibel zu sein.

Beachten Sie, dass auf vielen Systemen /bin/shauf bash, auf anderen auf verschiedene Shells verwiesen werden kann. Es ist dashzum Beispiel ein Symlink zu Debian und Ubuntu. Auch wenn /bin/shes sich um eine Verknüpfung handelt bash, ändert sich das Verhalten der Shell, wenn sie aufgerufen wird als sh(from man bash, emphasis mine):

Wenn bash mit dem Namen sh aufgerufen wird, wird versucht, das Startverhalten historischer Versionen von sh so genau wie möglich nachzuahmen, wobei auch der POSIX-Standard eingehalten wird. Beim Aufruf als interaktive Login-Shell oder als nicht interaktive Shell mit der Option --login wird zuerst versucht, die Befehle aus / etc / profile und ~ / .profile in dieser Reihenfolge zu lesen und auszuführen. Die Option --noprofile kann verwendet werden, um dieses Verhalten zu verhindern. Wenn bash als interaktive Shell mit dem Namen sh aufgerufen wird, sucht es nach der Variablen ENV und erweitert ihren Wert, falls dies der Fall ist
definiert und verwendet den erweiterten Wert als Namen einer Datei, die gelesen und ausgeführt werden soll. Da eine als sh aufgerufene Shell nicht versucht, Befehle aus anderen Startdateien zu lesen und auszuführen, hat die Option --rcfile keine Auswirkung. Eine nicht interaktive Shell, die mit dem Namen sh aufgerufen wird, versucht nicht, andere Startdateien zu lesen. Beim Aufruf als sh wechselt bash in den Posix-Modus, nachdem die Startdateien gelesen wurden.

terdon
quelle
2

Wenn Kompatibilität mit "allen Unix-Systemen" unabdingbar ist - und wenn nicht, warum schreiben Sie ein Shell-Skript? - dann, ja, sollten Sie verwenden #! /bin/sh, da Bash nicht garantiert überall installiert werden kann , geschweige denn /bin.

Es ist tatsächlich viel, viel schlimmer. Wenn Sie Kompatibilität mit allen Unix-Systemen benötigen , gehören dazu Solaris und AIX, die ihre Shell-Umgebungen um 1995 eingefroren haben. Dies bedeutet, dass Sie Dinge wie die altmodische sort +NSyntax verwenden müssen - dass neuere Systeme weggefallen sind! Und es bedeutet auch, dass keine Shell-Funktionen, keine Arrays, keine [[ ... ]], keine ${foo#glob}, keine $(( ... ))für die Arithmetik, möglicherweise keine $( ... )-Stil-Befehlssubstitution, kleine und nicht dokumentierte Obergrenzen dafür, wie groß die Eingabe sein kann, ...

Sie können wahrscheinlich davonkommen , wenn Sie sich nicht um so viel Kompatibilität kümmern, aber wenn es überhaupt ein Problem ist, empfehle ich Ihnen nachdrücklich, eine Sprache zu wählen, die weniger schrecklich ist als Shell. Der grundlegende Perl - Interpreter ist eher wahrscheinlich als Bash verfügbar sein.

zwol
quelle
Vielen Dank. Wie ursprünglich angegeben "In meinem Fall sind Ubuntu (Debian) und OSX das einzige Betriebssystem, das mich interessiert." Dies sind die einzigen 2 Systeme, die ich in den letzten 5 Jahren verwendet habe (und ich benutze sie sehr oft). Deshalb schreibe ich ein Shell-Skript, das nur mit ihnen funktioniert. Ich brauche überhaupt kein universelles Skript und die damit verbundenen Einschränkungen.
Michael Durrant
@MichaelDurrant In diesem Fall müssen und sollten Sie kein Shell-Skript schreiben. Sie sollten stattdessen eine der zahlreichen besseren Skriptsprachen verwenden, die eine Option sind, wenn Sie keine vollständige Portabilität benötigen.
6.