Zdrojování skript spustí příkazy v aktuálním shell proces.
Probíhá skript spustí příkazy v novém shell proces.
Pokud chcete, aby skript změnil prostředí ve vašem aktuálně spuštěném prostředí, použijte zdroj. použijte spustit jinak.
"prostředí" jsou věci jako aktuální pracovní adresář a proměnné prostředí. také nastavení shellu (mimo jiné funkce historie a dokončení). je jich víc, ale ty jsou nejviditelnější.
Pokud chcete více podrobností, čtěte dále.
Terminologie
Abychom objasnili některé běžné nejasnosti ohledně syntaxe k provedení a syntaxe ke zdroji:
./myscript
Toto se provede myscript
za předpokladu, že soubor je spustitelný a nachází se v aktuálním adresáři. Úvodní tečka a lomítko (./
) označuje aktuální adresář. To je nutné, protože aktuální adresář obvykle není (a obvykle by neměl být) v $PATH
.
myscript
Toto se provede myscript
pokud je soubor spustitelný a nachází se v nějakém adresáři v $PATH
.
source myscript
Toto bude zdroj myscript
. Soubor nemusí být spustitelný, ale musí to být platný skript shellu. Soubor může být v aktuálním adresáři nebo v adresáři $PATH
.
. myscript
Toto bude také zdroj myscript
. Toto "pravopis" je oficiální, jak je definováno v POSIX. Bash definován source
jako alias k tečce.
a pro úplnost:
exec myscript
Tím se ukončí aktuální shell a poté se místo ukončeného shellu spustí myscript. To znamená, že když je myscript hotový, neexistuje žádný starý shell, do kterého by se bylo možné vrátit. exec
je výkonná, ale zřídka potřebná.
Na konec jsem dal několik odkazů pro více informací o těchto tématech.
Ukázka
Zvažte myscript.sh
s následujícím obsahem:
#!/bin/sh
# demonstrate setting a variable
echo "foo: "$(env | grep FOO)
export FOO=foo
echo "foo: "$(env | grep FOO)
# demonstrate changing of working directory
echo "PWD: "$PWD
cd somedir
echo "PWD: "$PWD
Před spuštěním skriptu nejprve zkontrolujeme aktuální prostředí:
$ env | grep FOO
$ echo $PWD
/home/lesmana
Proměnná FOO
není definován a jsme v domovském adresáři.
Nyní provádíme soubor:
$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
Znovu zkontrolujte prostředí:
$ env | grep FOO
$ echo $PWD
/home/lesmana
Proměnná FOO
není nastaven a pracovní adresář se nezměnil.
Výstup skriptu jasně ukazuje, že proměnná byla nastavena a adresář byl změněn. Následná kontrola ukazuje, že proměnná není nastavena a adresář se nezměnil. Co se stalo? Změny byly provedeny v novém skořápka. aktuální shell vytvořil nové shell ke spuštění skriptu. Skript běží v novém prostředí a všechny změny prostředí se projeví v novém prostředí. Po dokončení skriptu je nový shell zničen. Všechny změny prostředí v novém shellu jsou zničeny s novým shellem. V aktuálním shellu se vytiskne pouze výstupní text.
Nyní zdroj soubor:
$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir
Znovu zkontrolujte prostředí:
$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir
Proměnná FOO je nastavena a pracovní adresář se změnil.
Zdrojem skriptu se nevytvoří nový shell. Všechny příkazy se spouštějí v aktuálním prostředí a změny prostředí se projeví v aktuálním prostředí.
Všimněte si, že v tomto jednoduchém příkladu je výstup spouštění stejný jako při získávání skriptu. To nemusí být nutně vždy případ.
Další ukázka
Zvažte následující skript pid.sh
:
#!/bin/sh
echo $$
(speciální proměnná $$
expanduje na PID aktuálně běžícího procesu shell)
Nejprve vytiskněte PID aktuálního shellu:
$ echo $$
25009
Zdroj skriptu:
$ source pid.sh
25009
Spusťte skript, poznamenejte si PID:
$ ./pid.sh
25011
Zdroj znovu:
$ source pid.sh
25009
Provést znovu:
$ ./pid.sh
25013
Můžete vidět, že získávání skriptu běží ve stejném procesu, zatímco provádění skriptu vždy vytváří nový proces. Tento nový proces je nový shell, který byl vytvořen pro provádění skriptu. Zdrojem skriptu se nevytvoří nový shell a PID tedy zůstane stejné.
Shrnutí
Jak zdroj, tak spuštění skriptu spustí příkazy ve skriptu řádek po řádku, jako byste tyto příkazy zadávali ručně řádek po řádku.
Rozdíly jsou:
- Když spustíte skript, který otevíráte, nový shell, zadejte příkazy do nového shellu, zkopírujte výstup zpět do vašeho aktuálního shellu a poté nový shell zavřete. Jakékoli změny prostředí se projeví pouze v novém prostředí a po zavření nového prostředí budou ztraceny.
- Když zdroj skript, který zadáváte příkazy ve vašem aktuálním skořápka. Jakékoli změny prostředí se projeví a zůstanou ve vašem aktuálním prostředí.
Pokud chcete, aby skript změnil prostředí ve vašem aktuálně spuštěném prostředí, použijte zdroj. použijte spustit jinak.
Viz také:
- https://stackoverflow.com/questions/6331075/why-do-you-need-dot-slash-before-script-name-to-run-it-in-bash
- https://askubuntu.com/questions/182012/is-there-a-difference-between-and-source-in-bash-after-all
- https://stackoverflow.com/questions/18351198/what-are-the-uses-of-the-exec-command-in-shell-scripts
Spuštění skriptu jej spustí v samostatném podřízeném procesu, tj. ke zpracování skriptu je vyvolána samostatná instance shellu. To znamená, že žádné proměnné prostředí atd., definované ve skriptu nemohou být aktualizován v nadřazeném (aktuálním) shellu.
Zdroj skriptu znamená, že je analyzován a spuštěn samotným aktuálním shellem. Je to, jako byste napsali obsah skriptu. Z tohoto důvodu nemusí být zdrojový skript spustitelný. Ale musí být spustitelný, pokud ho samozřejmě spouštíte.
Pokud máte v aktuálním shellu poziční argumenty, nezmění se.
Pokud tedy mám soubor a.sh
obsahující:
echo a $*
a já ano:
$ set `date`
$ source ./a.sh
Dostávám něco jako:
a Fri Dec 11 07:34:17 PST 2009
Vzhledem k tomu:
$ set `date`
$ ./a.sh
dává mi:
a
Doufám, že to pomůže.
sourcing je v podstatě stejný jako psaní každého řádku skriptu do příkazového řádku jeden po druhém...
Provedení spustí nový proces a poté spustí každý řádek skriptu, přičemž pouze upraví aktuální prostředí tím, co vrátí.