Es gibt verschiedene Möglichkeiten, ein Skript auszuführen. Die mir bekannten sind:
/path/to/script # using the path (absolute or relative)
. script # using the . (dot)
source script # using the `source` command
Sind die mehr davon? Was sind die Unterschiede zwischen ihnen? Gibt es Situationen, in denen ich eine und keine andere verwenden muss?
shell-script
executable
phunehehe
quelle
quelle
Antworten:
Eine andere Möglichkeit besteht darin, den Interpreter aufzurufen und den Pfad zum Skript zu übergeben:
Der Punkt und die Quelle sind gleichwertig. (BEARBEITEN: Nein, sie sind nicht: Wie KeithB in einem Kommentar zu einer anderen Antwort ausführt, funktioniert "." Nur in bash-bezogenen Shells, wobei "source" sowohl in bash- als auch in csh-bezogenen Shells funktioniert.) Das Skript wird in ausgeführt -place (als ob Sie das Skript genau dort kopiert und eingefügt hätten). Dies bedeutet, dass alle Funktionen und nicht lokalen Variablen im Skript verbleiben. Es bedeutet auch, dass Sie immer noch da sind, wenn das Skript eine CD in einem Verzeichnis erstellt.
Die anderen Methoden zum Ausführen eines Skripts führen es in einer eigenen Subshell aus. Variablen im Skript sind nach Abschluss des Vorgangs noch nicht aktiv. Wenn das Skript die Verzeichnisse geändert hat, hat dies keine Auswirkungen auf die aufrufende Umgebung.
/ path / to / script und / bin / sh script unterscheiden sich geringfügig. Typischerweise hat ein Skript am Anfang einen "shebang", der so aussieht:
Dies ist der Pfad zum Skriptinterpreter. Wenn ein anderer Interpreter angegeben wird als bei der Ausführung, verhält er sich möglicherweise anders (oder funktioniert überhaupt nicht).
Beispielsweise beginnen Perl-Skripte und Ruby-Skripte mit (jeweils):
und
Wenn Sie eines dieser Skripte ausführen
/bin/sh script
, funktionieren sie überhaupt nicht.Ubuntu verwendet eigentlich keine Bash-Shell, sondern eine sehr ähnliche namens dash. Skripte, die Bash erfordern, funktionieren möglicherweise etwas falsch, wenn sie mit dem
/bin/sh script
Bash-Interpreter aufgerufen werden, da Sie gerade ein Bash-Skript aufgerufen haben.Ein weiterer kleiner Unterschied zwischen dem direkten Aufrufen des Skripts und der Übergabe des Skriptpfads an den Interpreter besteht darin, dass das Skript als ausführbar markiert sein muss, um es direkt auszuführen, aber nicht, um den Pfad an den Interpreter zu übergeben.
Eine weitere geringfügige Änderung: Sie können eine der folgenden Möglichkeiten zum Ausführen eines Skripts mit dem Präfix eval versehen
und so weiter. Es ändert eigentlich nichts, aber ich dachte, ich würde es aus Gründen der Gründlichkeit einbeziehen.
quelle
sh
entsprichtdash
, aber nicht anbash
.Die meisten Leute debuggen Shell-Skripte, indem sie dem Skript die folgenden Debug-Flags hinzufügen :
Dies bedeutet jedoch, dass Sie die Datei mit einem Editor öffnen müssen (vorausgesetzt, Sie haben die Berechtigung, die Datei zu bearbeiten), indem Sie eine Zeile wie "
set -x
Speichern Sie die Datei" hinzufügen und dann die Datei ausführen. Wenn Sie fertig sind, müssen Sie die gleichen Schritte ausführen und entfernenset -x
, usw. usw. Dies kann mühsam sein.Anstatt all das zu tun, können Sie die Debugging-Flags in der Befehlszeile setzen:
quelle
emulate sh 2>/dev/null
meine Shell-Skripte ganz oben zu schreiben. Wenn es mit zsh ausgeführt wird, wird es in den POSIX-kompatiblen Modus versetzt. Wenn die Linie mit anderen Muscheln ausgeführt wird, hat sie keine Auswirkung. Dann kann ich das Skript mit ausführenzsh -x /path/to/script
. Ich mag zsh hier, weil es bessere Spuren liefert als bash oder ksh.Shawn J. Goff machte viele gute Punkte, enthielt aber nicht die ganze Geschichte:
Viele System-Skripte (wie zB in init.d, in / etc usw.) haben einen Shebang
#!/bin/sh
, sind aber/bin/sh
tatsächlich eine symbolische Verknüpfung zu einer anderen Shell - früher/bin/bash
, heute/bin/dash
. Aber wenn einer von ihnen als aufgerufen wird/bin/sh
, verhalten sie sich anders, dh sie bleiben im POSIX-Kompatibilitätsmodus.Wie machen sie das? Nun, sie untersuchen, wie sie aufgerufen wurden.
Kann ein Shellscript selbst testen, wie es aufgerufen wurde, und abhängig davon verschiedene Dinge tun? Ja, kann es. Die Art und Weise, wie Sie es aufrufen, kann immer zu unterschiedlichen Ergebnissen führen, aber es wird natürlich selten getan, um Sie zu ärgern. :)
Als Faustregel gilt: Wenn Sie eine bestimmte Shell wie Bash lernen und Befehle aus einem Bash-Tutorial schreiben, geben Sie
#!/bin/bash
die Überschrift ein#!/bin/sh
, sofern nicht anders angegeben. Anderenfalls könnten Ihre Befehle fehlschlagen. Und wenn Sie selbst kein Skript geschrieben haben, rufen Sie es direkt auf (./foo.sh
,bar/foo.sh
), anstatt eine Shell zu erraten (sh foo.sh
,sh bar/foo.sh
). Der Shebang sollte die richtige Shell aufrufen.Und hier sind zwei andere Arten der Anrufung:
quelle
.
undsource
sind insofern äquivalent, als sie keinen Unterprozess erzeugen, sondern Befehle in der aktuellen Shell ausführen. Dies ist wichtig, wenn das Skript Umgebungsvariablen festlegt oder das aktuelle Arbeitsverzeichnis ändert.Wenn Sie den Pfad verwenden oder angeben,
/bin/sh
wird ein neuer Prozess erstellt, in dem Befehle ausgeführt werden.quelle
Ich überlege, ob es noch mehr gibt ...
.
undsource
sind gleich. Nach der Ausführung werden alle Änderungen der Umgebung inscript
beibehalten. Normalerweise wird es verwendet, um eine Bash-Bibliothek zu erstellen, sodass die Bibliothek in vielen verschiedenen Skripten wiederverwendet werden kann.Es ist auch eine gute Möglichkeit, das aktuelle Verzeichnis zu behalten. Wenn Sie das Verzeichnis im Skript ändern, wird es nicht in der Shell angewendet, in der Sie das Skript ausführen. Wenn Sie es jedoch zum Ausführen verwenden, wird nach dem Beenden des Skripts das aktuelle Verzeichnis beibehalten.
quelle
.
Funktioniert nur in sh / bash und verwandten Shells.source
funktioniert auch in csh und verwandten shells.Zählt " userland exec " anders? Userland exec lädt Code und lässt ihn ohne Verwendung eines Systemaufrufs execve () ausführen.
quelle
Führt das Skript in der aktuellen Shell aus, wenn sich das Verzeichnis nicht im Pfad befindet.
quelle
. und source sind zumindest in zsh ein bisschen anders (das ist es, was ich benutze), weil
Funktioniert, während
nicht, es braucht
quelle