Question Quelle est la différence entre exécuter un script Bash et l'exécuter?


Quelle est la différence entre exécuter un script Bash comme A et trouver un script Bash comme B?

A
> ./myscript

B
> source myscript

213
2017-12-11 15:24


origine




Réponses:


Réponse courte: le sourcing lancera les commandes dans le processus shell actuel. L'exécution exécutera les commandes dans un nouveau processus shell. encore confus? alors s'il vous plaît continuer à lire la longue réponse.

Terminologie:

Pour clarifier certaines confusions courantes concernant la syntaxe à exécuter et la syntaxe à utiliser pour la source:

./myscript

Exécuter  myscript à condition que le fichier soit exécutable et situé dans le répertoire en cours. La barre oblique principale (./) indique le répertoire en cours. Ceci est nécessaire car le répertoire en cours n'est généralement pas dans $PATH.

myscript

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

source myscript

La source  myscript. le fichier n'a pas besoin d'être exécutable mais il doit s'agir d'un script de shell valide. Le fichier peut être dans le répertoire courant ou dans un répertoire dans $PATH.

. myscript

La source  myscript. Cette syntaxe est défini par POSIX. Bash défini source comme alias de la commande point.

Manifestation:

Considérer 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 d'abord l'environnement actuel:

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

La variable FOO n'est pas défini et nous sommes dans le répertoire personnel.

Maintenant nous exécuter 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éfini 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 ultérieure montre que la variable n'est pas définie et que le répertoire n'a pas été modifié. Qu'est-il arrivé? Les modifications ont été apportées dans un Nouveau coquille. le actuel coquille a engendré un Nouveau shell pour exécuter le script. Le script s'exécute 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. Tous les changements apportés à l'environnement dans le nouveau shell sont détruits avec le nouveau shell. Seul le texte de sortie est imprimé dans le shell actuel.

Maintenant nous la 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 recherche du script ne crée pas de nouveau shell. Toutes les commandes sont exécutées dans le shell en cours et les modifications apportées à l'environnement prennent effet dans le shell en cours.

Notez que dans cet exemple simple, la sortie de l'exécution est la même que celle du script. Ce n'est pas nécessairement toujours le cas.

Une autre démonstration:

Envisagez le script suivant pid.sh:

#!/bin/sh
echo $$

(la variable spéciale $$ développe le PID du processus en cours d'exécution du shell

Tout d'abord, imprimez le PID du shell actuel:

$ echo $$
25009

Source du script:

$ source pid.sh
25009

Exécutez le script, notez le PID:

$ ./pid.sh
25011

Source encore:

$ source pid.sh
25009

Exécuter à nouveau:

$ ./pid.sh
25013

Vous pouvez voir que la recherche du script dans le même processus lors de l'exécution du script crée un nouveau processus à chaque fois. Ce nouveau processus est le Nouveau shell qui a été créé pour l'exécution du script. La recherche du script ne crée pas un nouveau shell et le PID reste donc le même.

Résumé

L'approvisionnement et l'exécution du script exécutent les commandes du script ligne par ligne, comme si vous les saisissiez ligne par ligne.

Les différences sont les suivantes:

  • Lorsque vous exécuter le script que vous ouvrez un Nouveau shell, tapez les commandes dans le nouveau shell, copiez la sortie dans votre shell actuel, puis fermez le nouveau shell. Toute modification apportée à l'environnement ne prendra effet que dans le nouveau shell et sera perdue une fois le nouveau shell fermé.
  • Lorsque vous la source le script que vous tapez les commandes dans votre actuel coquille. 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 execute autrement.


Voir également:


277
2017-08-16 21:58



Une des utilisations du sourcing consiste à créer une forme rudimentaire de fichier de configuration pour vos scripts. Vous commencez par définir diverses variables à leurs valeurs par défaut, puis vous créez quelque chose comme myscript.conf - et ce script source peut avoir des instructions d'affectation qui remplacent toutes les valeurs souhaitées. Comme le script source ne commence pas par # / bin / bash, il n’est pas conseillé de l’exécuter directement. - LawrenceC
Donc, la source est un peu comme l’exécuter dans une portée globale, et l’exécution crée une nouvelle étendue locale. Cela peut-il être étendu à une fonction dans un script? exécuter une fonction (normalement) ou la "source"? - aliteralmind
L'appel d'une fonction shell se comporte normalement comme un sourcing. L'appel d'une fonction shell à l'intérieur d'un sous-shell se comporte de la même manière que l'exécution. - lesmana
Y a-t-il une différence entre utiliser source myscript.sh et . myscript.sh? - Holloway
pratiquement aucune différence si vous utilisez bash. source est un alias à pointer dans bash. - 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 être mis à jour dans le shell parent (courant).

Trouver un script signifie qu’il est analysé et exécuté par le shell lui-même. C'est comme si vous avez tapé le contenu du script. Pour cette raison, le script généré ne doit pas nécessairement être exécutable. Mais il faut que ce soit exécutable si vous l'exécutez bien sûr.

Si vous avez des arguments positionnels 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

J'ai 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
2017-12-11 15:35



Bien que cette réponse soit correcte à tous points de vue, je trouve cela très difficile à comprendre car elle est démontrée à l’aide d’un autre concept (définition de paramètres positionnels), ce qui est encore plus déroutant que la différence de source et d’exécution. - lesmana


le sourcing est essentiellement identique à la saisie de chaque ligne du script à l'invite de commande, une à la fois ...

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


5
2017-12-11 15:27





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 les générer et ne pas les exécuter. Les exécutions sont indépendantes de l'environnement des parents.


4
2017-12-11 15:25





En plus de ci-dessus, exécuter le script en tant que ./myscript nécessite une autorisation d'exécution pour le fichier myscript alors que le sourcing ne nécessite aucune autorisation d'exécution. C'est pourquoi chmod +x myscript n'est pas nécessaire avant source myscript


4
2018-02-23 07:27



C'est vrai, mais si c'est un problème, vous pouvez toujours exécuter bash myscript. - Daniel Beck♦


Si je me souviens bien, l'exécution du script exécute l'exécutable dans le #! ligne avec le fichier de script en tant qu’argument (généralement en démarrant un nouveau shell et en fournissant le script efficacement 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 modifier votre shell actuel (par exemple, en fournissant un moyen de définir des fonctions de shell et d'exporter des variables d'environnement).


3
2017-12-11 15:27





source commande exécute le script fourni (la permission exécutable est pas obligatoire) dans le actuel environnement shell, tout en ./ exécute le fourni exécutable script dans un Nouveau coquille.

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


2
2018-03-27 14:04