Bash 4 wurde erfolgreich mit Homebrew und den zusätzlichen Schritten installiert, die erforderlich sind, um Bash 4 zu Ihrer Standard-Shell zu machen. Viele Anleitungen im Netz mit einfachem Googlen: Beispiel Bash 4 Upgrade Guide für Mac
/usr/local/bin/bash
/bin/bash
Skripte Ich kann den Shebang nicht steuern/modifizieren , da dies andere Benutzer beeinträchtigen würde. Es sei denn, ich musste manuell ändern und dann wiederherstellen, bevor ich mich auf die Quellcodeverwaltung festlegte. Eine andere Möglichkeit besteht darin, Folgendes einzugeben:bash some_script_with_bin_bash_shebang.sh
um die Verwendung der neu standardmäßigen bash 4-Shell zu erzwingen.
Ich muss dies immer nur für die Bash 4+-Funktionalität tun, die jetzt sehr verbreitet ist.
Hat jemand eine coole Technik, Problemumgehungen, um einen Shebang-Bash-Pfad wie folgt zu aliasieren: #!/bin/bash
zur neueren Bash 4-Shell unter /usr/local/bin/bash
?
Ohne offensichtlich die Datei zu verändern! ^_^ (z. B. Hinzufügen von #!/usr/bin/env bash
)
Dies ist heutzutage der Hauptgrund für die Verwendung eines anderen Krams:
#!/usr/bin/env bash
Dies wird die erste Bash im PATH verwenden, die höchstwahrscheinlich die neueste Version sein wird. Da sich /bin im Standardpfad ( getconf PATH
) befindet, fällt dies für diejenigen ohne benutzerdefinierte Bash problemlos zurück.
Erstens könnten Sie erwägen, einfach /bin/bash
durch eine aktuellere Version zu ersetzen.
Zweitens, wenn Sie damit Ihre Garantie nicht aufheben möchten und bereits ein Problem mit einem vorhandenen Skript haben, umgehen Sie dessen #!
Zeile, indem Sie es wie folgt aufrufen:
/path/to/bash4
/path/to/script.bash
args...
(Sie können einfach bash
anstelle des vollständigen Pfads verwenden, wenn Sie $PATH
in der richtigen Reihenfolge sind.)
Drittens, wenn dieses Skript spezifisch für Apple-Geräte ist und Bash-Version 4 haben muss, dann setzen Sie es immer explizit auf #!
/path/to/bash4
, da es keinen Vorteil bringt, es auf etwas anderes einzustellen. (Dies bedeutet nicht , dass Sie es in Ihrem Quell-Repository ändern, sondern es während der Installation auswählen; siehe unten.)
Viertens sollten Sie die Verwendung von https://gist.github.com/kurahaupo/8130030 in Erwägung ziehen – beachten Sie, dass die „Quell“-Version des Skripts außerhalb des beabsichtigten bin
Verzeichnisses liegen muss; Lassen Sie es zB in Ihrem Quell-Repo oder in einem temporären Verzeichnis (das nach dieser "Installation" gelöscht werden kann).
Fünftens, wenn Sie das ursprüngliche Skript wirklich nicht anfassen möchten, erstellen Sie ein Stub-Skript, das es aufruft:
#!/bin/sh
exec /path/to/bash4 /path/where/you/stashed/the/original/script "$@"
und installieren Sie diese in einem geeigneten bin
Verzeichnis.
Quelle vs. Bereitstellung
Ihre Frage zum Festlegen der #!
Zeile im Quellrepo unterstreicht ein weit verbreitetes Missverständnis über Skripte: die Idee, dass ein Skript, nur weil es "Text" ist, nicht in irgendeiner Weise "für die Verwendung vorbereitet" werden sollte.
Für andere Arten von Programmen ist es offensichtlich: Sie müssen kompiliert werden. Und wenn es sich um große Python- oder Perl-Skripte handelt, benötigen sie ein Paket oder Installationsprogramm, das alle Modulabhängigkeiten enthält.
Aber selbst ein Shell-Skript muss zumindest seinen Besitz und seine Berechtigungen haben und in einem bin
Verzeichnis abgelegt werden. Normalerweise ist dies entweder der Fall, wenn ein Paket für eine Geräteklasse erstellt wird, oder wenn das Skript auf einem Zielgerät installiert wird. Dies ist auch der geeignete Zeitpunkt, um die Leitung passend zur Einsatzumgebung einzustellen .#!
Ich empfehle nicht#!/usr/bin/env bash
Die weitverbreitete Werbung für #!/usr/bin/env
etwas schwächt die allgemeine Sicherheit, aber auf eine Art und Weise, die wahrscheinlich nicht die Leute, die es schreiben, beißt, sondern nur die Benutzer irgendwo im weiteren Verlauf. Daher empfehle ich es nicht ; Tatsächlich sage ich voraus, dass es irgendwann zurückkommen und Ihre Kunden beißen wird, oder die Kunden Ihrer Kunden, oder die Kunden Ihrer Kunden ... Kunden.
Es wird als "tragbar" beworben, aber das stimmt nicht wirklich: Android- und OpenWRT-Geräte haben nicht einmal /usr
viel weniger /usr/bin/env
, also ist es dort ziemlich nutzlos. In der Praxis sind die Hauptnutznießer also Apple-Benutzer.
Wenn das Skript eine neue Version von bash erfordert, reicht die Systemversion einfach nicht aus, daher ist es sinnlos, sie als Fallback zu verwenden. Wenn Sie jedoch nicht die neueste Version benötigen, ist es in Ordnung, sie als /bin/bash zu fixieren.
Kurz gesagt, wenn Sie ein Skript für Apple bereitstellen, das Bash Version 4 erfordert, sollten Sie verwenden #!
/path/to/bash4
, entweder wenn Sie das Skript in ein installierbares Paket einbauen oder wenn das Skript auf einem bestimmten Gerät installiert wird.
BEARBEITEN
Ich habe es /usr/local/bin/bash
durch ersetzt /path/to/bash4
, weil das etwas Verwirrung gestiftet hat. Der Punkt ist nicht, dass /usr/local/bin/bash
verwendet werden muss, sondern dass der vollständige Pfad zu bash4, was auch immer es ist, explizit angegeben werden sollte. Wenn Sie es vor der Installation nicht wissen, ist es sinnvoll, $PATH
dort nachzusehen, aber Sie möchten einen kurzen Test wie z
bash_path=$( type -p bash )
if ! "$bash_path" -c '[[ $BASH_VERSION > 4.2 ]]'
then
echo "ERROR: $bash_path isn't new enough"
exit 1
fi
{
printf '#!%s\n' "$bash_path"
tail -n+2 "$downloaded_file"
} > "$installpath"
chmod a=rx "$installpath"
sudo mv -vf /bin/bash /bin/bash_old
führt zumv: cannot move '/bin/bash' to '/bin/bash_old': Operation not permitted
Meine Problemumgehung besteht einfach darin, den Dolmetscher direkt anzurufen.
Also zum Beispiel, anstatt so etwas wie:
./foo.sh
Ich nenne es stattdessen mit:
bash ./foo.sh
Die erste Form (die './foo.sh' aufruft) übt den in der Shebang-Zeile definierten Interpreter aus und gibt Ihnen (unerwünschtes) Bash 3.x auf OSX (zumindest ab OSX Big Sur). Die zweite Form ignoriert jedoch die Shebang-Zeile und ruft die Version von bash auf, die Sie in Ihrem PATH haben. Wenn Ihr PATH „/usr/local/bin“ (oder wo auch immer Sie mit Brew installieren) vor „/bin“ vorkommt, führen Sie Ihr Skript mit der gewünschten Bash-Version aus, unabhängig davon, was in der Shebang-Zeile steht. Daher können Sie Ihr Skript mit Goodies ausführen, die bash 4.x+ benötigen (wie assoziative Arrays).
Dadurch wird das Ziel erreicht, das Skript überhaupt nicht ändern zu müssen, während es dennoch mit der gewünschten Version von bash ausgeführt wird. Zum jetzigen Zeitpunkt können Sie bash 5.x mit Brew erhalten, während OSX 11.2 „Big Sur“ immer noch mit /bin/bash in v3.x ausgeliefert wird.
Diese Methode passt am besten, wenn Sie für Plattformen entwickeln , auf denen „/bin/bash“ zuverlässig die gewünschte Version ist, Sie aber auf OSX entwickeln, auf dem „/bin/bash“ 3.x ist. Auf diese Weise können Sie mit der beabsichtigten Zielversion von bash entwickeln und testen, ohne die Shebang-Zeile des Skripts auf eine Weise zu ändern, die es auf Zielplattformen weniger zuverlässig macht. Insbesondere für Bash ziehe ich es auch vor, den #!/usr/bin/env-Trick nicht zu verwenden, da dies die Komplexität für Benutzer erhöht und die Komplexität der Unterstützung erhöhen kann.
Ich verstehe den Punkt, der zu Source vs. Deployment angesprochen wurde, und dass es keine absolute Anforderung gibt, Deployment-Änderungen an Shell-Skripten nicht zuzulassen. Es kann jedoch eine große Sache sein, die Shebang-Zeilen in der Versionskontrolle ändern zu dürfen und dies dazu zu führen, dass Änderungen in den Bereitstellungsprozessen erforderlich sind, und Sie haben möglicherweise keine Kontrolle darüber. Das Vorhandensein von Shell-Skripten, die einen Bereitstellungsprozess erfordern, der die Prüfsumme des ursprünglichen Codes ändert, verringert einen der wichtigsten „Einfachheits“-Vorteile der Verwendung von Bash-Shell-Skripten. Wenn Skripte als Teil eines größeren Produkts bereitgestellt werden, das sicherstellen kann, dass komplexe Installationsschritte zuverlässig ausgeführt werden, würde ich nichts dagegen einwenden. Aber wenn Skripte das Produkt sind, hat es einen großen Vorteil, die Komplexität der Bereitstellung auf „Entpacken aus einem Tarball“ zu beschränken.
RST
grg
RST
Wowfunhappy
/bin/bash
die Datei/bin/bash
und nicht eine völlig andere Datei/usr/local/bin/bash
? Die logisch korrekte Antwort lautet: "Weil das Skript dazu aufgefordert wurde, sollten Sie das Skript bearbeiten wenn du willst, dass es etwas anderes tut."