web-dev-qa-db-fra.com

Quelle est la différence entre l'exécution d'un script Bash et son sourcing?

Quelle est la différence entre l’exécution d’un script Bash tel que A et la création d’un script Bash tel que B?

A
> ./myscript

B
> source myscript
263
Scottie T

Réponse courte

Sourcing un script exécutera les commandes du processus actuel Shell.

L'exécution de un script exécutera les commandes dans un processus nouveau Shell.

Si vous êtes toujours confus, lisez la suite.

Terminologie

Pour clarifier une certaine confusion concernant la syntaxe à exécuter et la syntaxe à utiliser comme source:

./myscript

Ceci execute myscript à condition que le fichier soit exécutable et situé dans le répertoire en cours. Le point et la barre oblique (./) indiquent le répertoire en cours. Cela est nécessaire car le répertoire en cours ne figure généralement pas (et ne devrait normalement pas l'être) dans $PATH.

myscript

Ceci execute myscript si le fichier est exécutable et situé dans un répertoire de $PATH.

source myscript

Ce sera source myscript. Le fichier ne doit pas nécessairement être exécutable, mais il doit s'agir d'un script Shell valide. Le fichier peut être dans le répertoire en cours ou dans un répertoire dans $PATH.

. myscript

Cela va aussi source myscript. Cette "orthographe" est l'orthographe officielle définie par POSIX . Bash définit source comme un alias pour le point.

Manifestation

Considérez myscript.sh avec le contenu suivant:

#!/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

Avant d'exécuter le script, nous vérifions l'environnement actuel:

$ env | grep FOO
$ echo $PWD
/home/lesmana

La variable FOO n'est pas définie et nous nous trouvons dans le répertoire de base.

Maintenant nous exécutons le fichier:

$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

Vérifiez à nouveau l'environnement:

$ env | grep FOO
$ echo $PWD
/home/lesmana

La variable FOO n'est pas définie et le répertoire de travail n'a pas changé.

La sortie du script indique clairement que la variable a été définie et que le répertoire a été modifié. La vérification montre ensuite que la variable n'est pas définie et que le répertoire n'est pas modifié. Qu'est-il arrivé? Les modifications ont été apportées dans un nouveau Shell. Le actuel Shell a généré un nouveau Shell pour exécuter le script. Le script est exécuté dans le nouveau shell et toutes les modifications apportées à l'environnement prennent effet dans le nouveau shell. Une fois le script terminé, le nouveau shell est détruit. Toutes les modifications apportées à l'environnement dans le nouveau Shell sont détruites avec le nouveau Shell. Seul le texte de sortie est imprimé dans le shell actuel.

Maintenant nous source le fichier:

$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

Vérifiez à nouveau l'environnement:

$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir

La variable FOO est définie et le répertoire de travail a été modifié.

La création du script ne crée pas de nouveau shell. Toutes les commandes sont exécutées dans le shell actuel et les modifications apportées à l'environnement prennent effet dans le shell actuel.

Notez que dans cet exemple simple, le résultat de l'exécution est identique à l'obtention du script. Ce n'est pas forcément toujours le cas.

Une autre manifestation

Envisagez de suivre le script pid.sh:

#!/bin/sh
echo $$

(la variable spéciale $$ se développe en PID du processus Shell en cours d'exécution)

Imprimez d'abord le PID du shell actuel:

$ echo $$
25009

Source le script:

$ source pid.sh
25009

Exécutez le script, notez le PID:

$ ./pid.sh
25011

Source encore:

$ source pid.sh
25009

Exécutez à nouveau:

$ ./pid.sh
25013

Vous pouvez constater que la recherche du script s'exécute dans le même processus, alors que l'exécution du script crée un nouveau processus à chaque fois. Ce nouveau processus est le nouveau Shell créé pour l'exécution du script. La création du script ne crée pas de nouveau shell et le PID reste donc le même.

Résumé

La recherche et l’exécution du script exécutent les commandes dans le script ligne par ligne, comme si vous les tapiez à la main, ligne par ligne.

Les différences sont:

  • Lorsque vous exécutez le script que vous ouvrez un nouveau shell, entrez les commandes dans le nouveau shell, copiez la sortie dans votre shell actuel, puis fermez le nouveau. Toute modification de l'environnement ne prendra effet que dans le nouveau shell et sera perdue une fois le nouveau shell fermé.
  • Lorsque vous source le script, vous saisissez les commandes dans votre actuel Shell. Toute modification de l'environnement prendra effet et restera dans votre Shell actuel.

Utilisez source si vous souhaitez que le script modifie l'environnement dans votre Shell en cours d'exécution. use exécute autrement.


Voir également:

327
lesmana

L'exécution d'un script l'exécute dans un processus enfant distinct, c'est-à-dire qu'une instance distincte de Shell est appelée pour traiter le script. Cela signifie que toute variable d'environnement, etc., définie dans le script ne peut pas est mise à jour dans le Shell parent (actuel).

La création d'un script signifie qu'il est analysé et exécuté par le shell actuel. C'est comme si vous avez tapé le contenu du script. Pour cette raison, le script recherché ne doit pas nécessairement être exécutable. Mais il doit être exécutable si vous l'exécutez bien sûr.

Si vous avez des arguments de position dans le shell actuel, ils ne sont pas modifiés.

Donc, si j'ai un fichier a.sh contenant:

echo a $*

et je fais:

$ set `date`
$ source ./a.sh

Je reçois quelque chose comme:

a Fri Dec 11 07:34:17 PST 2009

Tandis que:

$ set `date`
$ ./a.sh

donne moi:

a

J'espère que cela pourra aider.

21
Alok

sourcing est essentiellement la même chose que taper chaque ligne du script dans la commande Invite, une à la fois ...

L'exécution démarre un nouveau processus, puis exécute chaque ligne du script, en modifiant uniquement l'environnement actuel en fonction de ce qu'il retourne.

9
John Weldon

En plus de ce qui précède, l’exécution du script en tant que ./myscript nécessite une autorisation d’exécution pour le fichier myscript, tandis que la recherche de sources n’exige aucune autorisation d’exécution. C'est pourquoi chmod +x myscript n'est pas requis avant source myscript

6
abs

Sourcing vous obtenez toutes les variables supplémentaires définies dans le script.
Donc, si vous avez des définitions de configuration ou de fonction, vous devez créer et non exécuter. Les exécutions sont indépendantes de l'environnement des parents.

5
Arkaitz Jimenez

Si je me souviens bien, l'exécution du script exécute le fichier exécutable dans la ligne #! avec le fichier de script en tant qu'argument (généralement, en démarrant un nouveau shell et en le localisant dans le nouveau shell, comme avec #!/bin/sh);
alors que la recherche du script exécute chaque ligne de votre environnement Shell actuel, ce qui est utile pour transformer votre Shell actuel (par exemple, en fournissant un moyen de définir les fonctions du Shell et d'exporter les variables d'environnement).

3
fd

La commande source exécute le script fourni (la permission de l'exécutable est non obligatoire ) dans l'environnement current Shell, tandis que ./ exécute le executable script fourni. dans un new Shell.

Vérifiez également cette réponse, par exemple: https://superuser.com/a/894748/432100

2
Harsh Vakharia