les scripts shell fonctionnent toujours sans #! (ligne sha-bang)

10

Je suis nouveau dans les scripts shell et de nombreux livres ont écrit qui utilisent la ligne #! (Sha-bang) au début du script pour invoquer l'interpréteur. Et cela invoquera un nouveau shell pour le script et fera l'interprétation ligne par ligne. de mon script de base fonctionne toujours sans la ligne magique.

donc mes questions sont:

  • d'où mon script de base a obtenu l'interprète.
  • comment le script a-t-il réussi à localiser l'interprète.

laissez-moi maintenant vous parler de mon script de base, il contient juste la ligne suivante:

echo "script de base sans les lignes magiques"

user1678213
la source

Réponses:

3

Si la ligne magique n'est pas fournie, un shell par défaut est utilisé pour exécuter le script. Ce shell par défaut peut être soit le shell Bourne (sh), ce qui est le cas dans certaines versions, mais dans certaines autres versions, le shell par défaut utilisé est le même que le shell de connexion pour l'exécuter. La chose est: ne laissez pas le système décider du shell, fournissez toujours le shell que vous voulez dans la première ligne.

Gourou
la source
1
yup..peut-être que mon shell actuel appelle un shell par défaut pour un script shell n'ayant pas de nombres magiques.
user1678213
1
@ user1678213 Oui, c'est votre shell (et non le noyau) qui fait ça.
Gilles 'SO- arrête d'être méchant'
1
Je crois que POSIX exige que / bin / sh soit utilisé dans ce cas.
vonbrand
2
@vonbrand Il s'agit d'une idée fausse courante. POSIX n'exige pas que le shell POSIX soit /bin/sh, juste pour être le premier shexécutable trouvé lors de l'exploration d'un PATH conforme.
jlliagre
3
C'est incorrect, ce n'est jamais le "shell de connexion" qui est utilisé pour l'exécuter. Ce qui peut arriver cependant, c'est que le shell appelant (si le script est appelé à partir d'un shell) peut avoir un enfant de lui-même qui l'interprète.
Stéphane Chazelas
8

Lorsque vous exécutez un programme, le noyau vérifie s'il démarre par une séquence d'octets magiques . Si le fichier exécutable commence par #!, le noyau interprète le reste de la ligne comme un nom d'interpréteur. Si le fichier exécutable commence par \177ELF(où \177est l'octet 127), il charge le fichier en tant qu'exécutable ELF ; c'est le type normal sur la plupart des systèmes Unix de nos jours.

Si le noyau ne reconnaît pas le format de fichier, il refuse d'exécuter le fichier et renvoie l'erreur ENOEXEC (erreur de format Exec). Lorsque le shell le remarque, il prend sur lui d'exécuter le programme en tant que script shell.

Pour en témoigner en action, ajoutez quelques commandes à votre script:

ps l $$
ls -l /proc/$$/exe
echo hello

(Ceci est pour Linux, ajustez pour les autres unités.) Essayez ensuite d'exécuter ce script à partir de divers shells. Vous verrez que certains shells engendrent de nouvelles instances d'eux-mêmes pour exécuter le script (bash, ksh93) tandis que d'autres /bin/shapparaissent (dash, pdksh, zsh).

Gilles 'SO- arrête d'être méchant'
la source
Que dois-je rechercher avec votre ls -lcommande? Ceci: lrwxrwxrwx 1 i 0 Oct 11 05:15 exe -> /bin/bash-? Si oui, que dit-il? En outre, remarqué que j'ai SHELL=/bin/bashsur env, mais le changer ne semble pas un changement de comportement. Peut-être que ce n'est pas lié?
Emanuel Berg
il semble que vous changiez la variable shell "SHELL". Si oui, alors vous modifiez uniquement la valeur de la variable shell SHELL.it ne modifiera pas votre shell.pour modifier votre shell, éditez le fichier / etc / passwd.
user1678213
2
@EmanuelBerg Oui (j'aurais dû écrire ls -l /proc/$$/exe, en fait). Les exeliens pointent vers le shell qui exécute votre script. Lorsque vous exécutez votre script, vous verrez que c'est bash qui interprète le script. Si vous l'exécutez depuis pdksh par exemple, il s'exécute /bin/sh. Je ne connais aucun shell qui utilise la SHELLvariable d'environnement ou le shell de connexion dans ce cas.
Gilles 'SO- arrête d'être méchant'
2
@ user1678213 La modification du shell dans /etc/passwdchange le shell qui est exécuté lorsque vous vous connectez via SSH ou sur une console texte. Cela ne change pas quel shell pourrait exécuter des scripts.
Gilles 'SO- arrête d'être méchant'
2
@ user1678213 J'ai vérifié ce que j'ai écrit ici en exécutant des tests. Aucun des shells que j'ai testés n'a cherché /etc/passwdà décider quel shell utiliser, ils ont soit créé une instance d'eux-mêmes, soit exécuté /bin/sh.
Gilles 'SO- arrête d'être méchant'
-2

C'est probablement l'une des 3 possibilités suivantes:

  1. Vous appelez le script directement avec l'interpréteur, IE: bash script.sh

  2. Le nom du fichier de script a une extension .sh, qui permet au système de rechercher le programme par défaut pour ce type de fichier

  3. L'environnement shell que vous utilisez exécute lui-même l '«écho», car je ne peux que deviner que le fichier de script est exécutable. Si, par exemple, vous allez utiliser un shell bash et avoir une commande dans votre fichier qui n'est utilisée que par ksh, alors vous verrez que cela ne fonctionnera pas.

Bonne chance!

bizna
la source
3
je ne l'ai pas appelé avec bash ni avec aucune extension.
user1678213
1
et l'environnement shell ne l'exécute pas parce que lorsque j'invoque la commande ps après avoir appelé mon script. La commande ps montre deux processus bash, ce qui signifie qu'il y a deux bash en cours d'exécution. l'un est mon shell bash de connexion et l'autre est bash pour mon basic_script
user1678213
1
2: le noyau ne fera rien de tel. Zsh peut le faire, et bash peut être tordu pour le faire. 3: Oui, mais cela varie un peu entre les obus, voir ma réponse.
Gilles 'SO- arrête d'être méchant'