C'est peut-être une question idiote, mais je la pose quand même. Si j'ai déclaré un shebang
#!/bin/bash
au début de my_shell_script.sh
, alors dois-je toujours invoquer ce script en utilisant bash
[my@comp]$bash my_shell_script.sh
ou puis-je utiliser par exemple
[my@comp]$sh my_shell_script.sh
et mon script détermine le shell en cours d'exécution en utilisant le shebang? Est-ce la même chose avec ksh
shell? J'utilise AIX.
scripting
executable
shebang
jrara
la source
la source
chmod +x my_shell_script.sh ; /path/to/my_shell_script.sh # or ./my_shell_script.sh if you happen to be in its directory
Réponses:
Le shebang
#!
est une instance lisible par l'homme d'un nombre magique composé de la chaîne d'octets0x23 0x21
, qui est utilisée par laexec()
famille de fonctions pour déterminer si le fichier à exécuter est un script ou un binaire. Lorsque le shebang est présent,exec()
exécutera l'exécutable spécifié après le shebang.Notez que cela signifie que si vous appelez un script en spécifiant l'interpréteur sur la ligne de commande, comme dans les deux cas donnés dans la question,
exec()
il exécutera l'interpréteur spécifié sur la ligne de commande, le script ne sera même pas examiné.Ainsi, comme d'autres l'ont noté, si vous souhaitez
exec()
appeler l'interpréteur spécifié sur la ligne shebang, le script doit avoir le bit exécutable défini et appelé en tant que./my_shell_script.sh
.Le comportement est facile à démontrer avec le script suivant:
Explication:
#!/bin/ksh
définitksh
pour être l'interprète.$$
contient le PID du processus en cours./proc/pid/exe
est un lien symbolique vers l'exécutable du processus (au moins sous Linux; sous AIX, /proc/$$/object/a.out est un lien vers l'exécutable).readlink
affichera la valeur du lien symbolique.Exemple:
Remarque : je le démontre sur Ubuntu, où le shell par défaut
/bin/sh
est un lien symbolique vers un tiret, c’est/bin/dash
-à-/bin/ksh
dire un lien symbolique vers/etc/alternatives/ksh
, qui à son tour est un lien symbolique vers/bin/pdksh
.la source
exec()
réponse à cette question est un appel système, la commandeexec
est un shell intégré. C'est pourquoi vous ne pouvez pas appeler unexec
programme à partir de Node.js ou de Java. Cependant, toute commande shell appelée, par exempleRuntime.exec()
en Java, est finalement traitée par l'exec()
appel système.child_process.{exec(),execFile(),spawn()
} tout serait mis en œuvre en utilisant le Cexec()
(à traversprocess
).Oui. En passant, ce n'est pas une question idiote. Une référence pour ma réponse est ici . Commencer un script avec #!
C'est ce qu'on appelle une ligne "shebang" ou "bang".
Ce n'est rien d'autre que le chemin absolu vers l'interprète Bash.
Il se compose d'un signe numérique et d'un caractère de point d'exclamation (#!), Suivi du chemin d'accès complet à l'interpréteur, tel que / bin / bash.
Tous les scripts sous Linux sont exécutés à l'aide de l'interpréteur spécifié sur une première ligne. Presque tous les scripts bash commencent souvent par #! / Bin / bash (en supposant que Bash a été installé dans / bin). Ainsi, Bash sera utilisé pour interpréter le script, même s'il est exécuté sous un autre shell. Le shebang a été introduit par Dennis Ritchie entre la version 7 Unix et la version 8 des laboratoires Bell. Il a ensuite été ajouté à la ligne BSD à Berkeley.
Ignorer une ligne d'interprétation (shebang)
Si vous ne spécifiez pas de ligne d'interpréteur, la valeur par défaut est généralement / bin / sh. Cependant, il est recommandé de définir la ligne #! / Bin / bash.
la source
#!/usr/bin/perl
#!/usr/local/bin/python
#!/usr/local/bin/ruby
autre entrée shebang utilisée pour prendre en charge plusieurs systèmes consiste à utiliser env pour localiser l’interpréteur que vous souhaitez utiliser, comme#!/usr/bin/env perl
#!/usr/bin/env python
env
, lequel devrait être réellement préféré? Python et Perl utilisent souventenv
, alors que sur les scripts de shell, ceci est souvent omis et shebang pointe vers la coque en question.env
trouver un programme dans $ PATH est un peu un bidouillage. Il ne définit pas les variables d'environnement comme son nom l'indique. $ PATH peut être un résultat différent pour différents utilisateurs. Mais cela aide les scripts à fonctionner sans modification sur les systèmes qui placent un interpréteur perl raisonnable à un endroit étrange.L'
exec
appel système du noyau Linux comprend shebangs (#!
) de manière nativeQuand vous faites sur bash:
sous Linux, cela appelle l'
exec
appel système avec le chemin./something
.Cette ligne du noyau est appelée sur le fichier transmis à
exec
: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25Il lit les tout premiers octets du fichier et les compare à
#!
.Si la comparaison est vraie, alors le reste de la ligne est analysé par le noyau Linux, qui effectue un autre
exec
appel avec le chemin/usr/bin/env python
et le fichier en cours comme premier argument:et cela fonctionne pour tout langage de script utilisant
#
un caractère de commentaire.Et oui, vous pouvez faire une boucle infinie avec:
Bash reconnaît l'erreur:
#!
se trouve simplement lisible par l’homme, mais ce n’est pas nécessaire.Si le fichier a démarré avec différents octets, l'
exec
appel système utilisera un autre gestionnaire. L’autre gestionnaire intégré le plus important concerne les fichiers exécutables ELF: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305, qui vérifie la présence d’octets7f 45 4c 46
(qui se trouve également être humain). lisible pour.ELF
). Confirmons cela en lisant les 4 premiers octets de/bin/ls
, qui est un exécutable ELF:sortie:
Ainsi, lorsque le noyau voit ces octets, il prend le fichier ELF, le met correctement en mémoire et lance un nouveau processus avec celui-ci. Voir aussi: https://stackoverflow.com/questions/8352535/how-does-kernel-get-an-executable-binary-file-running-under-linux/31394861#31394861
Enfin, vous pouvez ajouter vos propres gestionnaires Shebang avec le
binfmt_misc
mécanisme. Par exemple, vous pouvez ajouter un gestionnaire personnalisé pour les.jar
fichiers . Ce mécanisme prend même en charge les gestionnaires par extension de fichier. Une autre application consiste à exécuter de manière transparente des exécutables d’une architecture différente avec QEMU .Cependant, je ne pense pas que POSIX spécifie des shebangs: https://unix.stackexchange.com/a/346214/32558 , bien qu'il le mentionne dans les sections de justification, et sous la forme "si les scripts exécutables sont pris en charge par le système Pourrait arriver".
la source
./something
partir d'un shell ne passera pas par le chemin completexec
, mais exactement par le chemin entré. Pouvez-vous corriger cela dans votre réponse? Faitesecho "$0"
dans votre script et vous verrez que c'est le cas.En fait, si vous le prenez en conséquence, l'exécutable indiqué dans la ligne shebang n'est qu'un exécutable. Il est logique d’utiliser un interpréteur de texte comme exécutable, mais ce n’est pas nécessaire. Juste pour clarification et démonstration, j’ai fait un test plutôt inutile:
Nommé le fichier test.txt et définir le bit exectuable
chmod u+x test.txt
, puis « appelé » il:./test.txt
. Comme prévu, le contenu du fichier est sorti. Dans ce cas, le chat n'ignore pas la ligne shebang. Il affiche simplement toutes les lignes. Tout interprète utile devrait donc pouvoir ignorer cette ligne shebang. Pour bash, perl et PHP, il s’agit simplement d’une ligne de commentaire. Alors oui, ceux-ci ignorent la ligne shebang.la source
D'après ce que j'ai pu comprendre, chaque fois qu'un fichier contenant un bit exécutable est appelé et appelé, le noyau analyse l'en-tête du fichier afin de déterminer la marche à suivre (pour autant que je sache, vous pouvez ajouter des gestionnaires personnalisés pour les formats de fichier personnalisés via LKM). Si le fichier semble être un fichier texte avec un #! combinaison au début, son exécution est envoyée à un autre exécutable (généralement un shell), chemin vers lequel doit être spécifié directement après ledit shebang, dans la même ligne. Le noyau exécute ensuite le shell et passe le fichier à gérer.
En bref, peu importe le shell avec lequel vous appelez le script - le noyau distribuera l’exécution de la manière appropriée.
la source
bash ./myscript.sh
et./myscript.sh
.