La ligne #!
est utilisée avant le script est exécuté, puis ignoré lorsque le script s'exécute.
Vous demandez quelle est la différence entre une ligne de shebang et un commentaire ordinaire.
Une ligne commençant par #!
est tout autant un commentaire que toute autre ligne commençant par #
. Ceci est vrai si #!
est la première ligne du fichier ou ailleurs. #!/bin/sh
a un effet , mais il n'est pas lu par l'interpréteur lui-même .
#
n'est pas un commentaire dans tous les langages de programmation mais, comme vous le savez, il s'agit d'un commentaire de type Bourne incluant sh
et bash
(ainsi que la plupart des shells de style non-Bourne, comme%) code%). Il est également un commentaire en Python . Et c'est un commentaire dans une variété de fichiers de configuration qui ne sont pas vraiment des scripts (comme csh
).
Supposons qu'un script shell commence par /etc/fstab
. C'est un commentaire, et l'interpréteur (le shell) ignore tout sur la ligne après le caractère #!/bin/sh
.
L'objet d'une ligne #
n'est pas de donner des informations à l'interpréteur. Le but de la ligne #!
est d'indiquer au système d'exploitation (ou à tout processus qui lance l'interpréteur) quoi utiliser comme interpréteur .
-
Si vous appelez le script en tant que fichier exécutable, par exemple, en exécutant #!
, le système consulte la première ligne pour voir si commence par ./script.sh
, suivi de zéro espace ou plus, suivi d'un commander. Si c'est le cas, il exécute cette commande avec le nom du script comme argument. Dans cet exemple, il exécute #!
(ou, techniquement, /bin/sh script.sh
).
-
Si vous appelez le script en appelant explicitement l'interpréteur, la ligne /bin/sh ./script.sh
n'est jamais consultée. Donc, si vous exécutez #!
, la première ligne n'a aucun effet. Si la première ligne de sh script.sh
est script2.sh
, l'exécution de #!/usr/games/nibbles
n'essaiera pas d'ouvrir le script dans sh script2.sh
(mais nibbles
le fera).
Vous remarquerez que l’extension du script ( ./script2.sh
), si elle en a un, n’a aucun impact sur son exécution. Dans un système de type Unix, cela n'affecte généralement pas l'exécution du script. Sur certains autres systèmes, comme Windows, la ligne .sh
shebang peut être entièrement ignorée par le système et l'extension peut déterminer ce qui exécute les scripts. (Cela ne signifie pas que vous devez donner vos extensions de scripts, mais c'est l'une des raisons pour lesquelles, si vous le faites, elles devraient être correctes.)
#!
a été choisi pour atteindre cet objectif précisément car #!
commence un commentaire. La ligne #
est destinée au système et non à l'interpréteur et doit être ignorée par l'interpréteur.
Ligne Shebang pour les scripts Bash
Vous (à l'origine) avez dit que vous utilisez #!
pour les scripts #!/bin/sh
. Vous ne devriez le faire que si le script ne nécessite aucune des extensions bash
- bash
doit pouvoir exécuter le script. sh
n'est pas toujours un lien symbolique vers sh
. Souvent, y compris sur tous les systèmes Debian et Ubuntu récents à distance, bash
est un lien symbolique vers sh
.
Ligne Shebang pour les scripts Python
Vous avez également dit (dans la première version de votre question, avant d’éditer) que vous démarriez vos scripts Python avec dash
. Si vous voulez dire cela littéralement, alors vous devriez absolument arrêter de le faire. Si #!/bin/sh read by the interpretor
commence par cette ligne, l'exécution de hello.py
s'exécute:
/bin/sh read by the interpretor hello.py
./hello.py
essaiera d'exécuter un script appelé /bin/sh
(avec read
comme arguments), by the interpretor hello.py
sera (espérons-le) introuvable, et votre script Python ne sera jamais vu par un interpréteur Python.
Si vous faites cette erreur sans avoir le problème que je décris, vous appelez probablement vos scripts Python en spécifiant explicitement l’interpréteur (par exemple, read
), en ignorant la première ligne. Lorsque vous distribuez vos scripts à d’autres utilisateurs ou que vous les utilisez longtemps plus tard, il n’est peut-être pas évident que cela soit nécessaire pour qu’ils fonctionnent. Il vaut mieux les réparer maintenant. Ou du moins supprimer complètement la première ligne, de sorte que, si elles ne parviennent pas à s'exécuter avec python hello.py
, le message d'erreur aura un sens.
Pour les scripts Python, si vous savez où l’interpréteur Python est (ou va être), vous pouvez écrire la ligne ./
de la même manière:
#!/usr/bin/python
Ou, si c'est un script Python 3, vous devez spécifier #!
, puisque python3
est presque toujours Python 2 :
#!/usr/bin/python3
Cependant, le problème est que, bien que python
soit supposé exister toujours, et que /bin/sh
existe presque toujours sur les systèmes où /bin/bash
est fourni avec le système d'exploitation, Python peut exister à divers endroits.
Par conséquent, de nombreux programmeurs Python l'utilisent à la place:
#!/usr/bin/env python
(ou bash
pour Python 3.)
Cela fait que le script utilise #!/usr/bin/env python3
comme étant au "bon endroit" au lieu de compter sur env
au bon endroit. C'est une bonne chose parce que:
-
python
est presque toujours situé dans env
.
- Sur la plupart des systèmes, quel que soit
/usr/bin
devrait exécuter votre script est celui qui apparaît en premier dans python
. À partir de PATH
avec hello.py
make #!/usr/bin/env python
exécutez ./hello.py
, ce qui équivaut (virtuellement) à l'exécution de /usr/bin/env python hello.py
.
La raison pour laquelle vous ne pouvez pas utiliser python hello.py
est que:
- Vous voulez que l’interpréteur spécifié soit donné par un chemin absolu (c’est-à-dire commençant par
#!python
).
- Le processus appelant exécutera
/
dans le répertoire en cours. Le comportement de recherche dans le chemin lorsque la commande ne contient pas de barre oblique est un comportement de shell spécifique.
Parfois, un script Python ou autre qui n’est pas un script shell aura une ligne shebang commençant par python
où #!/bin/sh ...
est un autre code. Ceci est parfois correct, car il existe des moyens d’appeler le shell compatible Bourne ( ...
) avec des arguments lui permettant d’appeler un interpréteur Python. (L'un des arguments contiendra probablement sh
.) Cependant, dans la plupart des cas, python
est plus simple, plus élégant et plus susceptible de fonctionner comme vous le souhaitez.
Lignes de shebang dans d’autres langues
De nombreux langages de programmation et de script, ainsi que certains autres formats de fichiers, utilisent #!/usr/bin/env python
comme commentaire. Pour chacun d'entre eux, un fichier dans la langue peut être exécuté par un programme qui le prend en argument en spécifiant le programme sur la première ligne après #
.
Dans certains langages de programmation, #!
n'est normalement pas un commentaire, mais comme cas particulier, la première ligne est ignorée si elle commence par #
. Cela facilite l'utilisation de la syntaxe #!
même si #!
ne fait pas autrement un commentaire sur une ligne.
Lignes de shebang pour les fichiers qui ne s'exécutent pas en tant que scripts
Bien que ce soit moins intuitif, tout fichier dont le format de fichier peut contenir une première ligne commençant par #
suivi du chemin complet d'un exécutable peut avoir une ligne shebang. Si vous faites cela, et que le fichier est marqué comme exécutable, vous pouvez l'exécuter comme un programme ... en l'ouvrant comme un document.
Certaines applications utilisent ce comportement intentionnellement. Par exemple, dans VMware, les fichiers #!
définissent des machines virtuelles. Vous pouvez "exécuter" une machine virtuelle comme s'il s'agissait d'un script car ces fichiers sont marqués comme étant exécutables et ont une ligne shebang leur permettant d'être ouverts dans un utilitaire VMware.
Lignes de shebang pour les fichiers qui ne s'exécutent pas comme des scripts mais agissent comme des scripts de toute façon
.vmx
supprime les fichiers. Ce n'est pas un langage de script. Toutefois, un fichier qui démarre rm
et qui est marqué comme exécutable peut être exécuté et, lorsque vous l'exécutez, #!/bin/rm
y est appelé en le supprimant.
Ceci est souvent conceptualisé comme "le fichier se supprime". Mais le fichier ne fonctionne pas vraiment du tout. Cela ressemble plus à la situation décrite ci-dessus pour les fichiers rm
.
Cependant, comme la ligne .vmx
facilite l'exécution d'une commande simpliste (y compris les arguments de ligne de commande), vous pouvez effectuer certains scripts de cette manière. Comme exemple simple de "script" plus sophistiqué que #!
, considérez:
#!/usr/bin/env tee -a
Cela prend l’entrée de l’utilisateur de manière interactive, la renvoie à l’utilisateur ligne par ligne et l’ajoute à la fin du fichier "script".
Utiles? Pas très. Conceptuellement intéressant? Totalement! Oui. (Un peu.)
Concepts conceptuels et de programmation similaires sur le plan conceptuel (juste pour le plaisir)