Wann ist #!/bin/bash
besser geeignet als #!/bin/sh
in einem Shell-Skript?
linux
shell-script
Hendré
quelle
quelle
bash
Funktionen und Syntax anstelle vonsh
Funktionen und Syntax verwenden.vim
Highlight wirdbash
Ismen , wenn Ihr Skript das hat#!/bin/sh
shebang. Ich ändere es nur,bash
wenn die Dinge haarig genug werden, um Bash-Features zu benötigen.$(...)
ist besonders widerlich. Einige von ihnen sind auch subtil [<(...)
undcmd >& file
erhalten keine Fehlerhervorhebung, zum Beispiel haben sie keine spezielle Hervorhebung für das, was sie bedeuten, mit oder ohneg:is_bash
]Antworten:
Zusamenfassend:
Es gibt mehrere Shells, die eine Obermenge der POSIX-sh-Spezifikation implementieren . Auf verschiedenen Systemen kann
/bin/sh
es sich um eine Verknüpfung zu ash, bash, dash, ksh, zsh usw. handeln. (Es wird jedoch immer sh-kompatibel sein - niemals csh oder fish.)Solange Sie sich nur an
sh
Features halten, können Sie (und sollten es wahrscheinlich auch) verwenden,#!/bin/sh
und das Skript sollte einwandfrei funktionieren, unabhängig davon, um welche Shell es sich handelt.Wenn Sie anfangen, bash-spezifische Funktionen (z. B. Arrays) zu verwenden, sollten Sie bash speziell anfordern. Selbst wenn
/bin/sh
bash bereits auf Ihrem System aufgerufen wird, wird es möglicherweise nicht auf allen anderen Systemen ausgeführt, und Ihr Skript wird dort nicht ausgeführt. (Dasselbe gilt natürlich auch für zsh und ksh.) Sie können Shellcheck verwenden , um Bashismen zu identifizieren.Auch wenn das Skript nur für den persönlichen Gebrauch gedacht ist, werden Sie bemerken, dass sich einige Betriebssysteme
/bin/sh
während eines Upgrades ändern - z. B. unter Debian war es Bash, wurde aber später durch einen sehr minimalen Gedankenstrich ersetzt. Skripte, die Bashismen verwendeten, aber#!/bin/sh
plötzlich kaputt waren.Jedoch:
Auch
#!/bin/bash
ist nicht sehr richtig. Auf verschiedenen Systemen kann bash in/usr/bin
oder/usr/pkg/bin
oder leben/usr/local/bin
.Eine zuverlässigere Option ist
#!/usr/bin/env bash
$ PATH. (Auch wenn dasenv
Tool selbst nicht streng garantiert ist,/usr/bin/env
funktioniert es immer noch auf mehr Systemen als dies der/bin/bash
Fall ist.)quelle
/bin/sh
, wird versucht,sh
Features zu imitieren (siehe Manpage ). Nicht sicher, ob Bash-spezifische Features in diesem Modus verfügbar sind.env
tool ist ein posix tool, das es in den meisten Distributionen gibt, aber ich bin mir nicht sicher, da manche posix nicht respektieren./bin
: " Anwendungen sollten beachten, dass der Standard-PATH für die Shell weder / bin / sh noch / usr / bin / sh sein kann und bestimmt werden sollte durch Abfrage des von getconf PATH zurückgegebenen PATH, wobei sichergestellt wird, dass der zurückgegebene Pfadname ein absoluter Pfadname und keine eingebaute Shell ist ". Siehe auch diese Frage und speziell diese Antwort .#!
Skripte arbeiten zu lassen?echo foo ^ cat
emittiertfoo ^ cat
in POSIX sh, und emittiert nurfoo
in Bourne (wie^
ein Rohr Charakter besteht).Verwenden Sie den Shebang, der der Shell entspricht, die Sie tatsächlich zum Entwickeln und Debuggen Ihres Skripts verwendet haben. Dh wenn Ihre Login-Shell ist
bash
und Sie Ihr Skript als ausführbar in Ihrem Terminal ausführen, verwenden Sie#!/bin/bash
. Gehen Sie nicht einfach davon aus, dass Sie, da Sie keine Arrays (oderbash
Funktionen, die Ihnen bekannt sind) verwendet haben, die von Ihnen gewünschte Shell auswählen können. Es gibt viele subtile Unterschiede zwischen Shells (echo
, Funktionen, Schleifen, wie Sie es nennen), die ohne geeignete Tests nicht entdeckt werden können.Bedenken Sie Folgendes: Wenn Sie das Programm verlassen
#!/bin/bash
und Ihre Benutzer es nicht haben, wird ihnen eine eindeutige Fehlermeldung angezeigt, wie zDie meisten Benutzer können dieses Problem in weniger als einer Minute beheben, indem sie das entsprechende Paket installieren. Wenn Sie andererseits den shebang durch
#!/bin/sh
einen anderen ersetzen und auf einem System testen, zu dem/bin/sh
ein Symlink besteht,/bin/bash
sind Ihre Benutzer, die keinen habenbash
, in Schwierigkeiten. Sie sehen höchstwahrscheinlich eine kryptische Fehlermeldung wie:Dies kann Stunden dauern, und es wird keine Ahnung geben, welche Shell sie hätten verwenden sollen.
Es gibt nicht viele Gründe, warum Sie im shebang eine andere Schale verwenden möchten. Ein Grund ist, wenn die von Ihnen verwendete Shell nicht weit verbreitet ist. Eine andere
sh
Möglichkeit besteht darin, eine Leistung zu erzielen, die auf einigen Systemen erheblich schneller ist, UND Ihr Skript wird zu einem Leistungsengpass. Testen Sie in diesem Fall Ihr Skript gründlich mit der Zielshell und ändern Sie dann den Shebang.quelle
Sie sollten immer nur verwenden
#! /bin/sh
.Sie sollten niemals bash (oder zsh oder fish oder ...) -Erweiterungen in einem Shell-Skript verwenden.
Sie sollten immer nur Shell-Skripte schreiben, die mit einer Implementierung der Shell-Sprache funktionieren (einschließlich aller "Utility" -Programme, die mit der Shell selbst verbunden sind). In diesen Tagen können Sie wahrscheinlich nehmen POSIX.1-2001 ( nicht -2008) als maßgeblich für das, was die Shell und Dienstprogramme sind in der Lage, aber bewusst sein , dass Sie eines Tages aufgefordert werden , in den Hafen Ihr Skript an ein Legacy - System (zB Solaris oder AIX), deren Shell und Dienstprogramme um 1992 eingefroren wurden.
Was im Ernst ?!
Ja, im Ernst.
Hier ist die Sache: Shell ist eine schreckliche Programmiersprache. Das Einzige, was es zu bieten hat,
/bin/sh
ist der einzige Skript-Interpreter, über den jede Unix-Installation garantiert verfügt.Hier ist die andere Sache: Einige Iterationen des Perl 5-Interpreters (
/usr/bin/perl
) sind in einer zufällig ausgewählten Unix-Installation mit größerer Wahrscheinlichkeit verfügbar als in einer anderen(/(usr|opt)(/(local|sfw|pkg)?)?/bin/bash
. Andere gute Skriptsprachen (Python, Ruby, node.js usw. - ich werde sogar PHP und Tcl in diese Kategorie aufnehmen, wenn ich sie mit Shell vergleiche) sind in etwa so verfügbar wie Bash und andere erweiterte Shells.Wenn Sie die Möglichkeit haben, ein Bash-Skript zu schreiben, können Sie stattdessen eine Programmiersprache verwenden, die nicht schrecklich ist.
Nun, einfache Shell-Skripte, die nur ein paar Programme in einer Sequenz von einem Cron-Job oder so ausführen, es ist nichts Falsches daran, sie als Shell-Skripte zu belassen. Einfache Shell-Skripte benötigen jedoch weder Arrays noch Funktionen oder
[[
Ähnliches. Und Sie sollten nur dann komplizierte Shell-Skripte schreiben, wenn Sie keine andere Wahl haben. Beispielsweise sind Autoconf-Skripte immer noch Shell-Skripte. Diese Skripte müssen jedoch auf jeder Inkarnation ausgeführt werden/bin/sh
, die für das zu konfigurierende Programm relevant ist. und das heißt, sie können keine Erweiterungen verwenden. Sie müssen sich heutzutage wahrscheinlich nicht mehr um alte proprietäre Unixe kümmern, aber Sie sollten sich wahrscheinlich um aktuelle Open-Source-BSDs kümmern, von denen einige nicht installiert werdenbash
standardmäßig und eingebettete Umgebungen, die Ihnen nur eine minimale Shell undbusybox
.Abschließend Sie der Moment finden sie wollen eine Funktion , die in der tragbaren Shell - Sprache nicht verfügbar ist, das ist ein Zeichen dafür , dass das Skript zu kompliziert worden ist ein Shell - Skript zu bleiben. Schreiben Sie es stattdessen in einer besseren Sprache um.
quelle
sh
. Dies ist jedoch weit davon entfernt, zu behaupten, dass Sie niemals andere Muscheln verwenden sollten. Täglich werden Tausende (wahrscheinlich noch viel mehr) Skripte geschrieben, und die überwiegende Mehrheit dieser Skripte wird immer nur auf einer einzelnen Maschine ausgeführt. Ihr Rat ist im Produktionscode sinnvoll, aber nicht für die täglichen "sysdaminy" -Jobs, für die die meisten Skripte geschrieben wurden. Wenn ich weiß, dass mein Skript immer nur von mir und auf einem Linux-Computer verwendet wird, ist bash in Ordnung.Im Allgemeinen wird die schnellere Shell verwendet, wenn Zeit wichtiger als Funktionalität ist. sh ist häufig zum Bindestrich geneigt und wird häufig für Cron-Tasks oder Batch-Vorgänge von root verwendet, bei denen jede (Nano-) Sekunde zählt.
quelle
Um es noch kurz zu machen: Verwenden Sie
sh
diese Option , wenn die Portierbarkeit auf den meisten Systemen am wichtigsten ist undbash
wenn Sie einige ihrer spezifischen Funktionen, z. B. Arrays, verwenden möchten, sofern die Version von bash dies unterstützt.quelle
Der sicherste Weg. Wenn hart codiert, wäre das / usr / bin /,
shellOfChoice
aber eine neue Konvention, die ich immer jetzt zu verwenden versuche - da sich die 'Standardpositionen' über eine Änderung ändern können, ist PATH:#! / usr / bin / env sh oder
#! / usr / bin / env bash
oder für zB Perl-Skripte
#! / usr / bin / env perl -w
Wenn Sie einen Grund dafür haben, dass ein Skript NIEMALS automatisch einen neuen PATH aufnimmt, lassen Sie es natürlich weiterhin fest codieren - und dann sollte / usr / bin / something der wahrscheinlichste Pfad sein.
quelle