Étant donné que le fichier ne fait partie d'aucun type d'exécutable reconnu par le système, et en supposant que vous avez la permission d'exécuter ce fichier, l' execve()appel système échoue généralement avec une erreur ENOEXEC( pas un exécutable ).
Ce qui se passe alors dépend de l'application et / ou de la fonction de bibliothèque utilisée pour exécuter la commande.
Cela peut être par exemple un shell, la fonction execlp()/ execvp()libc.
La plupart des autres applications utiliseront l'une de ces applications lorsqu'elles exécuteront une commande. Ils invoqueront un shell par exemple au moyen de la system("command line")fonction libc qui invoquera généralement shpour analyser cette ligne de commande (dont le chemin peut être déterminé au moment de la compilation (comme /bin/shvs /usr/xpg4/bin/shsur Solaris)), ou invoquer le shell stocké $SHELLpar eux-mêmes comme viavec sa !commande, et xterm -e 'command line'et de nombreuses autres commandes ( su user -cinvoquera le shell de connexion de l'utilisateur au lieu de $SHELL).
Généralement, un fichier texte sans shebang qui ne commence pas par #est considéré comme un shscript. Ce shqui variera cependant.
execlp()/ execvp(), lors du execve()retour, il ENOEXECsera généralement invoqué sh. Pour les systèmes qui en ont plus d'un shcar ils peuvent se conformer à plus d'une norme, shcelle-ci sera généralement déterminée au moment de la compilation (de l'application utilisant execvp()/ execlp()en liant un autre bloc de code qui fait référence à un chemin différent sh). Par exemple, sur Solaris, ce sera /usr/xpg4/bin/sh(un standard, POSIX sh) ou /bin/sh(le shell Bourne (un shell obsolète) sur Solaris 10 et les versions antérieures, ksh93 dans Solaris 11).
En ce qui concerne les coquilles, il y a beaucoup de variations. bash, AT&T ksh, le shell Bourne interprètera généralement le script lui-même (dans un processus enfant sauf s'il execest utilisé) après avoir simulé un execve(), c'est-à-dire annuler toutes les variables non exportées, fermer tous les fds close-on-exec, supprimer tous les pièges personnalisés, alias, fonctions ... ( bashinterprétera le script en shmode). yashs'exécutera (avec shcomme argv[0]ainsi en shmode) pour l'interpréter.
zsh, pdksh, ashCoquilles à base invoqueront généralement sh( dont le trajet déterminé au moment de la compilation).
Pour cshet tcsh(et pour shcertains des premiers BSD), si le premier caractère du fichier est #, ils s'exécuteront eux-mêmes pour l'interpréter, et shautrement. Cela remonte à une époque pré-shebang où l'on cshreconnaissait #comme commentaires mais pas le shell Bourne, donc #c'était un indice qu'il s'agissait d'un script csh.
fish(au moins la version 2.4.0), renvoie simplement une erreur en cas d' execve()échec (il ne tente pas de le traiter comme un script).
Certains shells (comme bashAT&T ksh) essaieront d'abord de déterminer de manière heuristique si le fichier est probablement destiné à être un script ou non. Vous pouvez donc constater que certains shells refuseront d'exécuter un script s'il contient un caractère NUL dans les premiers octets.
Notez également que si execve()échoue avec ENOEXEC mais que le fichier a une ligne de shebang, certains shells essaient d'interpréter cette ligne de shebang eux-mêmes.
Voici donc quelques exemples:
- Quand
$SHELLest /bin/bash, xterm -e 'myscript with args'aura myscriptinterprété par bashen shmode. Tandis qu'avec xterm -e myscript with args, xtermutilisera execvp()donc le script sera interprété par sh.
su -c myscriptsous Solaris 10 où rootest /bin/shet /bin/shest le shell de connexion, le shell Bourne aura été myscriptinterprété par le shell Bourne.
/usr/xpg4/bin/awk 'BEGIN{system("myscript")'sous Solaris 10, il sera interprété par /usr/xpg4/bin/sh(idem pour /usr/xpg4/bin/env myscript).
find . -prune -exec myscript {} \;sous Solaris 10 (en utilisant execvp()) le fera interpréter par /bin/sheven avec /usr/xpg4/bin/find, même dans un environnement POSIX (un bug de conformité).
csh -c myscriptl'aura interprété par cshs'il commence par #, shsinon.
Dans l'ensemble, vous ne pouvez pas être sûr du shell qui sera utilisé pour interpréter ce script si vous ne savez pas comment et par quoi il sera invoqué.
Dans tous les cas, la syntaxe read -pest bash-only, vous voudrez donc vous assurer que le script est interprété par bash(et éviter cette .shextension trompeuse ). Soit vous connaissez le chemin de l' bashexécutable et utilisez:
#! /path/to/bash -
read -p ...
Ou vous pouvez essayer de vous fier à une $PATHrecherche de l' bashexécutable (en supposant qu'il bashsoit installé) en utilisant:
#! /usr/bin/env bash
read -p ...
(se envtrouve presque partout dans /usr/bin). Alternativement, vous pouvez le rendre compatible POSIX + Bourne, auquel cas vous pouvez l'utiliser /bin/sh. Tous les systèmes auront un /bin/sh. Sur la plupart d'entre eux, il sera (pour la plupart) compatible POSIX, mais vous pouvez toujours y trouver de temps en temps un shell Bourne.
#! /bin/sh -
printf >&2 'Enter a user name: '
read user
printf '%s\n' "$user"