El #!
la ligne est utilisée antes de le script est exécuté, puis ignoré quand le script s'exécute.
Vous demandez quelle est la différence entre un ligne shebang et un commentaire ordinaire.
Une ligne commençant par #!
est tout autant un commentaire que n'importe quelle autre ligne qui commence par #
. Ceci est vrai si le #!
est la première ligne du fichier, ou n'importe où ailleurs. #!/bin/sh
a un effet mais il n'est pas lu par l'interprète lui-même .
#
n'est pas un commentaire dans tous les langages de programmation mais, comme vous le savez, c'est un commentaire dans les shells de type Bourne, notamment sh
y bash
(ainsi que la plupart des shells de style non-Bourne, tels que csh
). C'est également un commentaire en Python . Et c'est un commentaire dans une variété de fichiers de configuration qui ne sont pas vraiment scripts du tout (comme /etc/fstab
).
Supposons qu'un Shell Shell commence par #!/bin/sh
. Il s'agit d'un commentaire, et l'interpréteur (le Shell) ignore tout ce qui se trouve sur la ligne qui suit l'élément #
caractère.
L'objectif d'un #!
n'est pas de donner des informations à l'interprète. Le but de la #!
est d'indiquer au système d'exploitation (ou au processus qui lance l'interpréteur) ce qu'il faut utiliser comme interprète .
-
Si vous invoquez le script comme un fichier exécutable, par exemple, en exécutant ./script.sh
le système consulte la première ligne pour voir si elle commence par #!
suivi de zéro ou plusieurs espaces, suivi d'une commande. S'il le fait, il exécute cette commande avec le nom du script comme argument. Dans cet exemple, il exécute /bin/sh script.sh
(ou, techniquement, /bin/sh ./script.sh
).
-
Si vous invoquez le script en appelant explicitement l'interpréteur, la fonction #!
La ligne n'est jamais consultée. Ainsi, si vous exécutez sh script.sh
la première ligne n'a aucun effet. Si script2.sh
La première ligne de l'article est #!/usr/games/nibbles
en cours d'exécution sh script2.sh
n'essaiera pas d'ouvrir le script en nibbles
(mais ./script2.sh
volonté).
Vous remarquerez que dans les deux cas, l'extension du script ( .sh
), s'il en a un, a un impact sur la façon dont il est géré. Dans un système de type Unix, cela n'affecte généralement pas la façon dont le script est exécuté. Sur certains autres systèmes, comme Windows, l'option #!
La ligne shebang pourrait être entièrement ignorée par le système, et l'extension pourrait déterminer ce qui exécute les scripts. (Cela ne signifie pas que vous devez donner à vos scripts des extensions, mais c'est une des raisons pour lesquelles, si vous le faites, elles devraient être correctes).
#!
a été choisi pour servir précisément cet objectif parce que #
commence un commentaire. Le site #!
est pour le système, pas pour l'interprète, et elle doit être ignorée par l'interprète.
Ligne Shebang pour les scripts de Bash
Vous avez dit (à l'origine) que vous utilisez #!/bin/sh
para bash
scripts. Vous ne devriez le faire que si le scripts ne requiert aucun des éléments suivants bash
Les extensions sh
doit être capable d'exécuter le script. sh
n'est pas toujours un lien symbolique vers bash
. Souvent, y compris sur tous les systèmes Debian et Ubuntu récents à distance , sh
est un lien symbolique vers dash
.
Ligne Shebang pour Python scripts
Vous avez aussi dit (dans la première version de votre question, avant modification) que vous démarrez vos scripts Python avec #!/bin/sh read by the interpretor
. Si vous voulez dire cela littéralement, alors vous devriez définitivement arrêter de le faire. Si hello.py
commence par cette ligne, en exécutant ./hello.py
s'exécute :
/bin/sh read by the interpretor hello.py
/bin/sh
va essayer d'exécuter un script appelé read
(avec by the interpretor hello.py
comme ses arguments), read
ne sera (espérons-le) pas trouvé, et votre script Python ne sera jamais vu par un interprète Python.
Si vous faites cette erreur mais n'avez pas le problème que je décris, vous invoquez probablement vos scripts Python en spécifiant explicitement l'interpréteur (par exemple, python hello.py
), ce qui fait que la première ligne est ignorée. Lorsque vous distribuez vos scripts à d'autres, ou que vous les utilisez longtemps après, il peut ne pas être clair que cela est nécessaire pour qu'ils fonctionnent. Il est préférable de les corriger maintenant. Ou au moins enlever la première ligne entièrement, de sorte que lorsqu'ils échouent à s'exécuter avec la commande ./
le message d'erreur aura un sens.
Pour les scripts de Python, si vous savez où se trouve (ou va se trouver) l'interpréteur Python, vous pouvez écrire la commande #!
de la même manière :
#!/usr/bin/python
Ou, s'il s'agit d'un script de Python 3, vous devez spécifier python3
puisque python
est presque toujours Python 2 :
#!/usr/bin/python3
Cependant, le problème est que pendant que /bin/sh
est censé exister toujours, et /bin/bash
existe presque toujours sur les systèmes où bash
est livré avec le système d'exploitation, Python peut exister à différents endroits.
C'est pourquoi de nombreux programmeurs Python l'utilisent à la place :
#!/usr/bin/env python
(Ou #!/usr/bin/env python3
pour Python 3).
Cela fait que le script dépend de env
être au "bon endroit" au lieu de s'appuyer sur python
être au bon endroit. C'est une bonne chose, parce que :
-
env
est presque toujours situé dans /usr/bin
.
- Sur la plupart des systèmes, l'un ou l'autre
python
debe exécuter votre script est celui qui apparaît en premier dans la fenêtre PATH
. Démarrage hello.py
con #!/usr/bin/env python
faire ./hello.py
exécuter /usr/bin/env python hello.py
ce qui équivaut (virtuellement) à exécuter python hello.py
.
La raison pour laquelle vous ne pouvez pas utiliser #!python
c'est que :
- Vous voulez que l'interprète spécifié soit donné par un chemin absolu (c'est-à-dire, commençant par
/
).
- Le processus appelant exécuterait
python
dans le répertoire actuel . Rechercher le chemin lorsque la commande ne contient pas de slash est un comportement spécifique Shell.
De temps en temps, un Python ou autre script qui n'est pas un script script aura une ligne shebang commençant par #!/bin/sh ...
donde ...
est un autre code. C'est parfois correct, car il existe certaines façons d'invoquer le Shell compatible avec Bourne ( sh
) avec des arguments pour qu'il invoque un interpréteur Python. (L'un des arguments contiendra probablement python
.) Cependant, dans la plupart des cas, #!/usr/bin/env python
est plus simple, plus élégant et plus susceptible de fonctionner comme vous le souhaitez.
Shebang Lines dans d'autres langues
De nombreux langages de programmation et de script, et certains autres formats de fichiers, utilisent #
comme un commentaire. Pour chacun d'entre eux, un fichier dans le langage peut être exécuté par un programme qui le prend comme argument en spécifiant le programme sur la première ligne après #!
.
Dans certains langages de programmation, #
n'est pas normalement un commentaire, mais dans un cas spécial, la première ligne est ignorée si elle commence par #!
. Cela facilite l'utilisation de #!
syntaxe même si #
ne fait pas autrement d'une ligne un commentaire.
Lignes Shebang pour les fichiers qui ne sont pas exécutés en tant que scripts.
Bien que cela soit moins intuitif, tout fichier dont le format peut accueillir 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 alors l'exécuter comme un programme... et l'ouvrir comme un document.
Certaines applications utilisent ce comportement intentionnellement. Par exemple, dans VMware, .vmx
définissent les machines virtuelles. Vous pouvez "exécuter" une machine virtuelle comme s'il s'agissait d'un script parce que ces fichiers sont marqués comme exécutables et possèdent une ligne shebang qui permet de les ouvrir dans un utilitaire VMware.
Lignes Shebang pour les fichiers qui ne s'exécutent pas comme des Scrips mais qui agissent comme des scripts de toute façon
rm
supprime les fichiers. Il ne s'agit pas d'un langage de script. Cependant, un fichier qui démarre #!/bin/rm
et est marqué exécutable peut être exécuté, et quand vous l'exécutez, rm
est invoqué sur elle, la supprimant.
Ceci est souvent conceptualisé comme "le fichier se supprime lui-même". Mais le fichier ne s'exécute pas vraiment. Cela ressemble plus à la situation décrite ci-dessus pour .vmx
des fichiers.
Pourtant, parce que le #!
facilite l'exécution d'une commande simple (y compris les arguments de la ligne de commande), vous pouvez effectuer quelques scripts de cette manière. Comme exemple simple d'un "script" plus sophistiqué que #!/bin/rm
considère :
#!/usr/bin/env tee -a
Ceci prend l'entrée de l'utilisateur de manière interactive, le renvoie à l'utilisateur ligne par ligne, et l'ajoute à la fin du fichier "script".
Utile ? Pas très. Conceptuellement intéressant ? Totalement ! Oui. (Un peu.)
Concepts de programmation/scénario similaires (juste pour le plaisir)