Kurze Antwort
In Ihrer Frage verwendet der zweite Befehl weder die .
eingebaute Shell noch die source
eingebaute. Stattdessen führen Sie das Skript tatsächlich in einer separaten Shell aus, indem Sie es wie bei jeder anderen ausführbaren Datei über den Namen aufrufen. Dies gibt ihm einen separaten Variablensatz ( wenn Sie jedoch eine Variable in die übergeordnete Shell exportieren , ist sie eine Umgebungsvariable für einen beliebigen untergeordneten Prozess und wird daher in die Variablen einer untergeordneten Shell aufgenommen ). Wenn Sie das /
zu einem Leerzeichen ändern , würde das es mit dem .
eingebauten ausführen , was äquivalent zu ist source
.
Erweiterte Erklärung
Dies ist die Syntax der integrierten source
Shell, die den Inhalt eines Skripts in der aktuellen Shell (und damit mit den Variablen der aktuellen Shell) ausführt:
source testenv.sh
Dies ist die Syntax der .
integrierten Funktion, die das Gleiche bewirkt wie source
:
. testenv.sh
Diese Syntax führt das Skript jedoch als ausführbare Datei aus und startet eine neue Shell, um es auszuführen:
./testenv.sh
Das nutzt das .
eingebaute nicht . Ist vielmehr .
Teil des Pfads zu der Datei, die Sie ausführen. Im Allgemeinen können Sie jede ausführbare Datei in einer Shell ausführen, indem Sie sie mit einem Namen aufrufen, der mindestens ein /
Zeichen enthält. Am ./
einfachsten ist es also, eine Datei im aktuellen Verzeichnis voranzustellen. Wenn sich das aktuelle Verzeichnis nicht in Ihrem befindet PATH
, können Sie das Skript nicht mit dem Befehl ausführen testenv.sh
. Dies soll verhindern, dass Benutzer versehentlich Dateien im aktuellen Verzeichnis ausführen, wenn sie beabsichtigen, einen Systembefehl oder eine andere Datei auszuführen, die in einem in der PATH
Umgebungsvariablen aufgelisteten Verzeichnis vorhanden ist.
Da das Ausführen einer Datei nach Namen (anstatt mit source
oder .
) in einer neuen Shell erfolgt, verfügt sie über einen eigenen Satz von Shell-Variablen. Die neue Shell erbt die Umgebungsvariablen vom aufrufenden Prozess (in diesem Fall von Ihrer interaktiven Shell), und diese Umgebungsvariablen werden zu Shellvariablen in der neuen Shell. Damit eine Shell-Variable an die neue Shell übergeben werden kann, muss eine der folgenden Bedingungen erfüllt sein:
Die Shell-Variable wurde exportiert, sodass es sich um eine Umgebungsvariable handelt. Verwenden Sie dazu die export
eingebaute Shell. In Ihrem Beispiel können Sie export MY_VAR=12345
die Variable in einem Schritt festlegen und exportieren. Wenn sie bereits festgelegt ist, können Sie sie einfach verwenden export MY_VAR
.
Die Shell-Variable wird explizit für den von Ihnen ausgeführten Befehl festgelegt und übergeben, sodass sie für die Dauer des ausgeführten Befehls eine Umgebungsvariable ist. Dies führt normalerweise dazu , dass:
MY_VAR=12345 ./testenv.sh
Wenn MY_VAR
ein Shell - Variable ist , die nicht exportiert hat, kann man sogar läuft testenv.sh
mit MY_VAR
geben als Umgebungsvariable durch sie selbst einstellen :
MY_VAR="$MY_VAR" ./testenv.sh
./
Syntax für Skripte erfordert eine Hashbang-Zeile (korrekt)
Übrigens: Wenn Sie eine ausführbare Datei wie oben beschrieben aufrufen (und nicht mit den integrierten .
oder source
Shell-Funktionen), wird das zum Ausführen verwendete Shell-Programm in der Regel nicht von der Shell bestimmt, von der aus Sie sie ausführen . Stattdessen:
Bei Binärdateien kann der Kernel so konfiguriert sein, dass er Dateien dieses bestimmten Typs ausführt. Es untersucht die ersten beiden Bytes der Datei auf eine "magische Zahl" , die angibt, um welche Art von ausführbarer Binärdatei es sich handelt. So können ausführbare Binärdateien ausgeführt werden.
Dies ist natürlich äußerst wichtig, da ein Skript ohne eine Shell oder einen anderen Interpreter, der eine ausführbare Binärdatei ist, nicht ausgeführt werden kann! Außerdem sind viele Befehle und Anwendungen kompilierte Binärdateien und keine Skripte.
( #!
Ist die Textdarstellung der "magischen Zahl", die eine ausführbare Textdatei angibt.)
Bei Dateien, die in einer Shell oder einer anderen interpretierten Sprache ausgeführt werden sollen, sieht die erste Zeile folgendermaßen aus:
#!/bin/sh
/bin/sh
kann durch eine andere Shell oder einen anderen Interpreter ersetzt werden, mit dem das Programm ausgeführt werden soll. Ein Python-Programm könnte beispielsweise mit der folgenden Zeile beginnen:
#!/usr/bin/python
Diese Zeilen werden Hashbang, Shebang und eine Reihe anderer ähnlicher Namen genannt. Siehe diesen FOLDOC-Eintrag , diesen Wikipedia-Artikel und Wird #! / Bin / sh vom Interpreter gelesen? für mehr Informationen.
Wenn eine Textdatei als ausführbar markiert ist und Sie sie von Ihrer Shell aus ausführen (wie ./filename
), aber nicht damit beginnen #!
, kann der Kernel sie nicht ausführen. Wenn dies jedoch geschehen ist, wird Ihre Shell versuchen , es auszuführen, indem Sie ihren Namen an eine andere Shell übergeben. Es gibt einige Anforderungen gestellt auf , was Shell das ist ( „die Schale wird ein Befehl entspricht mit einer Shell ausführen aufgerufen ...“ ). In der Praxis führen einige Shells - einschließlich bash
* - eine andere Instanz von sich selbst aus, während andere sie verwenden/bin/sh
. Ich empfehle dringend, dass Sie dies vermeiden und stattdessen eine Hashbang-Zeile verwenden (oder das Skript ausführen, indem Sie es an den gewünschten Interpreter übergeben, z bash filename
. B. ).
* GNU Bash-Handbuch , 3.7.2 Befehlssuche und -ausführung: "Wenn diese Ausführung fehlschlägt, weil die Datei nicht im ausführbaren Format vorliegt und es sich nicht um ein Verzeichnis handelt, wird angenommen, dass es sich um ein Shell-Skript handelt, und die Shell führt es wie beschrieben aus in Shell-Skripten . "
source
ist, dass die Funktionen von Bash verfügbar wurden, ohne dass sie neu geladen oder gestartet werden mussten. Beispiel#!/bin/bash function olakease {echo olakease;}
. Sobald Sie es mit laden, könnensource file.sh
Sie direktolakease
von Bash anrufen . Das gefällt mir sehr. Source führt dann viele Dinge aus, der Punkt.
ist nur für die Ausführung und ist so etwas wie usebash file.sh