Il y a plusieurs façons d'exécuter un script, celles que je connais sont les suivantes:
/path/to/script # using the path (absolute or relative)
. script # using the . (dot)
source script # using the `source` command
Sont les plus de cela? Quelles sont les différences entre eux? Existe-t-il des situations dans lesquelles je dois utiliser l'une et pas l'autre?
shell-script
executable
phunehehe
la source
la source
Réponses:
Une autre méthode consiste à appeler l'interprète et à lui transmettre le chemin du script:
Le point et la source sont équivalents. (EDIT: non, ils ne le sont pas: comme le souligne KeithB dans un commentaire sur une autre réponse, "." Ne fonctionne que dans les shells liés à bash, où "source" fonctionne dans les shells lié à bash et csh.) Il exécute le script dans -place (comme si vous avez copié et collé le script ici). Cela signifie que toutes les fonctions et variables non locales du script restent. Cela signifie également que si le script insère un cd dans un répertoire, vous serez toujours là quand ce sera fait.
Les autres méthodes d'exécution d'un script seront exécutées dans son propre sous-shell. Les variables dans le script ne sont pas encore en vie quand c'est fait. Si le script a changé de répertoire, cela n’affecte pas l’environnement d’appel.
/ path / to / script et / bin / sh Les scripts sont légèrement différents. Typiquement, un script a un "shebang" au début qui ressemble à ceci:
C'est le chemin de l'interpréteur de script. S'il spécifie un interprète différent de celui que vous utilisez lorsque vous l'exécutez, il peut se comporter différemment (ou ne pas fonctionner du tout).
Par exemple, les scripts Perl et les scripts Ruby commencent par (respectivement):
et
Si vous exécutez l'un de ces scripts en même temps
/bin/sh script
, ils ne fonctionneront pas du tout.Ubuntu n’utilise pas le shell bash, mais un très similaire appelé dash. Les scripts qui nécessitent bash peuvent fonctionner légèrement mal lorsqu'ils sont appelés
/bin/sh script
car vous venez d'appeler un script bash à l'aide de l'interpréteur de tirets.Une autre petite différence entre l'appel direct du script et la transmission du chemin d'accès du script à l'interpréteur réside dans le fait que le script doit être marqué comme exécutable pour pouvoir l'exécuter directement, mais pas pour l'exécuter en transmettant le chemin d'accès à l'interpréteur.
Autre variante mineure: vous pouvez préfixer l’une de ces manières d’exécuter un script avec eval, vous pouvez donc avoir
etc. Cela ne change rien, mais je pensais l'inclure pour plus de précision.
la source
sh
correspond àdash
, mais pasbash
.La plupart des gens déboguent des scripts shell en ajoutant les indicateurs de débogage suivants au script:
Mais cela signifie que vous devez ouvrir le fichier avec un éditeur (en supposant que vous ayez le droit de modifier le fichier), en ajoutant une ligne comme
set -x
, enregistrez le fichier, puis exécutez le fichier. Ensuite, lorsque vous avez terminé, vous devez suivre les mêmes étapes et supprimer les élémentsset -x
, etc., etc. Cela peut être fastidieux.Au lieu de faire tout cela, vous pouvez définir les indicateurs de débogage sur la ligne de commande:
la source
emulate sh 2>/dev/null
au sommet de mes scripts shell. Lorsqu'il est exécuté avec zsh, cela le met en mode compatible POSIX. Lorsqu'elle est exécutée avec d'autres shells, la ligne n'a aucun effet. Ensuite, je peux exécuter le script aveczsh -x /path/to/script
. J'aime zsh ici car il fournit de meilleures traces que bash ou ksh.Shawn J. Goff a soulevé beaucoup de points positifs, mais n'inclut pas toute l'histoire:
Beaucoup de scripts système (comme dans init.d, dans / etc et ainsi de suite) ont un shebang
#!/bin/sh
, mais/bin/sh
sont en fait un lien symbolique vers un autre shell - autrefois/bin/bash
, de nos jours/bin/dash
. Mais lorsque l’un d’eux est appelé/bin/sh
, ils se comportent différemment, c’est-à-dire qu’ils restent en mode de compatibilité POSIX.comment font-ils ça? Eh bien, ils inspectent comment ils ont été invoqués.
Un script de shell peut-il tester lui-même comment il a été appelé et faire différentes choses, en fonction de cela? Oui il peut. Ainsi, la façon dont vous l'invoquez peut toujours conduire à des résultats différents, mais bien entendu, il est rarement fait pour vous embêter. :)
En règle générale: si vous apprenez un shell spécifique comme bash et écrivez des commandes à partir d'un tutoriel, insérez
#!/bin/bash
le titre, pas#!/bin/sh
, sauf indication contraire. Sinon, vos commandes pourraient échouer. Et si vous n'avez pas écrit vous-même un script, appelez-le directement (./foo.sh
,bar/foo.sh
) au lieu de deviner un shell (sh foo.sh
,sh bar/foo.sh
). Le shebang devrait invoquer la bonne coque.Et voici deux autres types d'invocation:
la source
.
etsource
sont équivalentes en ce sens qu’elles ne génèrent pas de sous-processus mais exécutent des commandes dans le shell actuel. Ceci est important lorsque le script définit des variables d'environnement ou modifie le répertoire de travail actuel.Utiliser le chemin ou le donner à
/bin/sh
crée un nouveau processus dans lequel les commandes sont exécutées.la source
Je me demande s'il y a plus ...
.
etsource
sont les mêmes. Après exécution, tous les changements d’environnementscript
seraient conservés. Habituellement, il est utilisé pour créer une bibliothèque Bash, afin que celle-ci puisse être réutilisée dans de nombreux scripts différents.C'est aussi un bon moyen de garder le répertoire actuel. Si vous changez de répertoire dans un script, il ne sera pas appliqué dans le shell dans lequel vous exécutez ce script. Mais si vous le sourcez pour l'exécuter, une fois le script terminé, le répertoire actuel sera conservé.
la source
.
ne fonctionne que dans sh / bash et les coquilles connexes.source
fonctionne également en csh et les coquilles connexes." Userland exec " compte-t-il différemment? Userland exec charge le code et l'exécute sans utiliser l'appel système execve ().
la source
Exécute le script dans le shell actuel lorsque le répertoire ne se trouve pas dans le chemin.
la source
. et la source sont un peu différentes en zsh au moins (c'est ce que j'utilise) car
Fonctionne, tandis que
ne pas, il faut
la source