À partir de la page Shell Command Language de la spécification POSIX:
Si la première ligne d'un fichier de commandes shell commence par les caractères "#!", Les résultats ne sont pas spécifiés.
Pourquoi le comportement de #!
non spécifié par POSIX? Je trouve déconcertant que quelque chose d'aussi portable et largement utilisé ait un comportement non spécifié.
exec()
fonction. Donc, la vérification par rapport à plusieurs coques ne vous dit pas vraiment à quel point il est portable.Réponses:
Je pense principalement parce que:
le comportement varie considérablement entre l'implémentation. Voir https://www.in-ulm.de/~mascheck/various/shebang/ pour tous les détails.
Il pourrait cependant maintenant spécifier un sous-ensemble minimum de la plupart des implémentations de type Unix: comme
#! *[^ ]+( +[^ ]+)?\n
(avec uniquement des caractères du jeu de caractères de nom de fichier portable dans ces un ou deux mots) où le premier mot est un chemin absolu vers un exécutable natif, la chose n'est pas trop long et comportement non spécifié si l'exécutable est setuid / setgid, et l'implémentation a défini si le chemin de l'interpréteur ou le chemin du script est transmisargv[0]
à l'interpréteur.POSIX ne spécifie de toute façon pas le chemin des exécutables. Plusieurs systèmes ont des utilitaires pré-POSIX dans
/bin
//usr/bin
et ont les utilitaires POSIX ailleurs (comme sur Solaris 10 où se/bin/sh
trouve un shell Bourne et celui POSIX est/usr/xpg4/bin
; Solaris 11 l'a remplacé par ksh93 qui est plus conforme POSIX, mais la plupart des autres les outils en/bin
sont encore anciens non POSIX). Certains systèmes ne sont pas POSIX mais ont un mode / émulation POSIX. Tout ce que POSIX exige, c'est qu'il y ait un environnement documenté dans lequel un système se comporte POSIXly.Voir Windows + Cygwin par exemple. En fait, avec Windows + Cygwin, la transgression est honorée lorsqu'un script est invoqué par une application cygwin, mais pas par une application Windows native.
Donc, même si POSIX a spécifié le mécanisme shebang, il ne pourrait pas être utilisé pour écrire des scripts POSIX
sh
/sed
/awk
... (notez également que le mécanisme shebang ne peut pas être utilisé pour écrire un scriptsed
/ fiableawk
car il ne permet pas de passer une fin d'option marqueur).Maintenant, le fait qu'il ne soit pas spécifié ne signifie pas que vous ne pouvez pas l'utiliser (eh bien, il dit que vous ne devriez pas commencer par la première ligne
#!
si vous vous attendez à ce qu'il ne s'agisse que d'un commentaire régulier et non d'une transe), mais POSIX ne vous donne aucune garantie si vous le faites.D'après mon expérience, l'utilisation de shebangs vous donne plus de garantie de portabilité que l'utilisation de la façon de POSIX d'écrire des scripts shell: laissez la she-bang, écrivez le script dans la
sh
syntaxe POSIX et espérez que tout ce qui invoque le script invoque un POSIX conformesh
, ce qui est très bien si vous savez que le script sera invoqué dans le bon environnement par le bon outil mais pas autrement.Vous devrez peut-être faire des choses comme:
Si vous souhaitez être portable sur Windows + Cygwin, vous devrez peut-être nommer votre fichier avec une extension
.bat
ou.ps1
et utiliser une astuce similaire pourcmd.exe
oupowershell.exe
invoquer le cygwinsh
sur le même fichier.la source
sh
, il n'aurait pas besoin d'une ligne de hachage car il serait exécuté par POSIXsh
.execlp
ouexecvp
ont été utilisés, non? Si je devais utiliserexecve
, cela entraînerait ENOEXEC?Vous ne regardez pas assez profondément.
Dans les années 80, ce mécanisme n'était pas de facto standardisé. Bien que Dennis Ritchie l'ait mise en œuvre, cette mise en œuvre n'avait pas atteint le public du côté AT&T de l'univers. Il n'était effectivement accessible au public et connu qu'en BSD; avec des scripts shell exécutables non disponibles sur AT&T Unix. Il n'était donc pas raisonnable de le normaliser. La situation est illustrée par ce doco contemporain, l'un des nombreux:
- Stephen Frede (1988). "Programmation sur System X Release Y". Bulletin d'information du groupe d'utilisateurs d'Unix Systems en Australie . Volume 9. Numéro 4. p. 111.Un point important ici est que vous regardez les shells, alors que l'existence de scripts shell exécutables est en fait une question de
exec…()
fonctions. Ce que font les shells comprend les précurseurs du mécanisme de script exécutable, qui se trouvent encore dans certains shells encore aujourd'hui (et également de nos jours obligatoires pour leexec…p()
sous - ensemble de fonctions), et est quelque peu trompeur. À cet égard, la norme doit aborder le fonctionnementexec…()
d'un script interprété, et au moment de la création de POSIX, il ne fonctionnait tout simplement pas en premier lieu sur une grande partie du spectre des systèmes d'exploitation cibles .Une question secondaire est de savoir pourquoi cela n'a pas été normalisé depuis, d'autant plus que le mécanisme du nombre magique pour les interprètes de script avait atteint le public du côté AT&T de l'univers et avait été documenté
-exec…()
dans la définition d'interface du système 5 , au tournant des années 1990. :exec
. System V Interface Definition . Volume 1. 1991.Malheureusement, le comportement reste aujourd'hui presque aussi largement différent qu'il l'était dans les années 80 et il n'y a pas de comportement vraiment commun à normaliser. Certains Unices (notamment HP-UX et FreeBSD, par exemple) ne prennent pas en charge les scripts comme interprètes de scripts. Que la première ligne soit un, deux ou plusieurs éléments séparés par des espaces varie entre MacOS (et les versions de FreeBSD avant 2005) et les autres. La longueur de chemin maximale prise en charge varie.
␀
et les caractères en dehors du jeu de caractères de nom de fichier portable POSIX sont délicats, tout comme les espaces de début et de fin. Ce que les 0e, 1er et 2e arguments finissent par être est également délicat, avec des variations importantes d'un système à l'autre. Certains sont actuellement conformes à POSIX mais non-Les systèmes Unix ne prennent toujours pas en charge un tel mécanisme, et le rendre obligatoire les convertirait en n'étant plus conforme à POSIX.Lectures complémentaires
script
. Manuel d'informations diverses de NetBSD . 2005-05-06.la source
Comme indiqué par certaines des autres réponses, les implémentations varient. Cela rend difficile la standardisation et la préservation de la compatibilité descendante avec les scripts existants. Cela est vrai même pour les systèmes POSIX modernes. Par exemple, Linux ne tokenise pas complètement la ligne shebang par des espaces. macOS ne permet pas à l'interpréteur de script d'être un autre script.
Voir également http://en.wikipedia.org/wiki/Shebang_(Unix)#Portability
la source