GNU/Linux >> Znalost Linux >  >> Linux

Jaký je rozdíl mezi prováděním skriptu Bash a jeho získáváním?

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í.


Linux
  1. Jak číst celý skript Shell před jeho spuštěním?

  2. Jaký je rozdíl mezi #!/usr/bin/env bash a #!/usr/bin/bash?

  3. Jaký je rozdíl mezi ls a l?

  1. Rozdíl mezi získáváním zdrojů („.“ nebo „zdrojem“) a spouštěním souboru v Bash?

  2. Rozdíl mezi příkazy v bash skriptu a příkazy v terminálu

  3. jaký je rozdíl mezi remount to umount/mount?

  1. Rozdíl mezi operátory Bash [[ Vs [ Vs ( Vs ((?

  2. Jaký je rozdíl mezi strtok_r a strtok_s v C?

  3. Jaký je rozdíl mezi nohoup a ampersand