Devrais-je utiliser un Shebang avec des scripts Bash?
j'utilise Bash
$ echo $SHELL
/bin/bash
et à partir d'il y a environ un an j'ai arrêté D'utiliser des Shebangs avec mes scripts Bash. Peut
Je profite de l'utilisation de #!/bin/sh
ou #!/bin/bash
?
mise à jour: dans certaines situations, un fichier n'est traité comme un script qu'avec le Shebang, exemple
$ cat foo.sh
ls
$ cat bar.sh
#!/bin/sh
ls
$ file foo.sh bar.sh
foo.sh: ASCII text
bar.sh: POSIX shell script, ASCII text executable
7 réponses
sur les systèmes de type UNIX, vous devez toujours démarrer les scripts avec une ligne shebang. L'appel système execve
(qui est responsable du démarrage des programmes) s'appuie sur sur un exécutable ayant soit un en-tête exécutable, soit une ligne shebang.
From FreeBSD execve manual page :
The execve() system call transforms the calling process into a new process. The new process is constructed from an ordinary file, whose name is pointed to by path, called the new process file. [...] This file is either an executable object file, or a file of data for an interpreter. [...] An interpreter file begins with a line of the form: #! interpreter [arg] When an interpreter file is execve'd, the system actually execve's the specified interpreter. If the optional arg is specified, it becomes the first argument to the interpreter, and the name of the originally execve'd file becomes the second argument
execve () exécute le programme pointé par nom de fichier. nom de fichier doit être soit un exécutable binaire, soit un script commençant par une ligne formulaire:
#! interpreter [optional-arg]
en fait, si un fichier n'a pas le bon "nombre magique" dans son en-tête, (comme un en-tête ELF ou #!
), execve
will fail avec l'erreur ENOEXEC (encore une fois de Page de manuel d'exécution de FreeBSD):
[ENOEXEC] le nouveau fichier de processus a l'accès approprié permission, mais a un nombre magique invalide dans son tête.
si le fichier a des permissions exécutables, mais pas de ligne shebang mais semble être un fichier texte, le comportement dépend de l'interpréteur de commandes que vous utilisez.
la plupart des coquilles semblent commencer un nouvelle instance d'eux-mêmes et nourrir le fichier, voir ci-dessous.
Puisqu'il n'y a aucune garantie que le script a été réellement écrit pour ce shell, cela peut fonctionner ou échouer de manière spectaculaire.
à Partir de tcsh(1) :
On systems which do not understand the `#!' script interpreter conven‐ tion the shell may be compiled to emulate it; see the version shell variable. If so, the shell checks the first line of the file to see if it is of the form `#!interpreter arg ...'. If it is, the shell starts interpreter with the given args and feeds the file to it on standard input.
de FreeBSD sh (1) :
If the program is not a normal executable file (i.e., if it
does not begin with the “magic number” whose ASCII representation is
“#!”, resulting in an ENOEXEC return value from execve(2)) but appears to
be a text file, the shell will run a new instance of sh to interpret it.
de bash (1):
If this execution fails because the file is not in executable format, and the file is not a directory, it is assumed to be a shell script, a file containing shell commands. A subshell is spawned to execute it.
vous ne pouvez pas toujours dépendre de l'emplacement d'un programme non standard comme bash. J'ai vu bash in /usr/bin
, /usr/local/bin
, /opt/fsf/bin
et /opt/gnu/bin
pour n'en citer que quelques-uns.
donc c'est généralement une bonne idée d'utiliser env
;
#!/usr/bin/env bash
si vous voulez que votre script soit portable, utilisez sh
au lieu de bash
.
#!/bin/sh
alors que les standards comme POSIX ne ne garantissent pas les chemins absolus des utilitaires standards, la plupart des systèmes de type UNIX semblent avoir sh
dans /bin
et env
dans /usr/bin
.
devraient toujours commencer par une ligne shebang. Si un script ne démarre pas avec cela, alors il peut être exécuté par le shell courant. Mais cela signifie que si quelqu'un qui utilise votre script utilise un shell différent de celui que vous utilisez, le script peut se comporter différemment. En outre, cela signifie que le script ne peut pas être exécuté directement à partir d'un programme (par exemple l'appel système C exec()
ou find -exec
), il doit être exécuté à partir d'un shell.
vous pourriez être intéressé par une description ancienne par Dennis Ritchie ( dmr
) qui a inventé le #!
:
de uucp Thu Jan 10 01: 37 :58 1980
.>À partir de dmr Jeu Jan 10 04:25:49 1980 à distance à partir de la recherche
Le système a été modifié de sorte que si un fichier être exécuté commence avec les personnages magiques #! le reste de l' ligne est entendu à être le nom d'un interprète pour les exécutée fichier. Auparavant (et fait toujours) le shell a fait une grande partie de ce travail; il s'exécute automatiquement sur un fichier texte avec le mode exécutable lorsque le nom du fichier texte a été tapé comme une commande. Mettre l'installation dans le système donne les avantages suivants.
1) Il rend les scripts shell plus comme de vrais fichiers exécutables, parce que ils peuvent faire l'objet de " exec.
2) Si vous faites un " ps " alors une telle commande est en cours d'exécution, de son vrai nom s'affiche à la place de "sh". De même, la comptabilité est effectuée sur la base de le nom réel.
3) les scripts Shell peuvent être définis-user-ID.
4) il est plus simple d'avoir des coques alternatives disponibles; par exemple si vous aimez le CSH de Berkeley il n'y a pas de question sur ce que shell doit interpréter un fichier.
5) Il permettra à d'autres interprètes de s'intégrer plus facilement.
pour profiter de cette merveilleuse occasion, mettre
#! /bin/sh
à la marge gauche de la première ligne de vos scripts shell. Vide après la ! sont OK. Utiliser un chemin complet (aucune recherche n'est effectuée). À l' moment la ligne entière est limitée à 16 caractères mais cette limite seront soulevées.
Espérons que cette aide
-
Si vous écrivez bash scripts, c'est à dire non portable de scripts contenant des bashisms, vous devriez garder à l'aide de la
#!/bin/bash
shebang juste pour être sûr que le bon interprète. Vous ne devez pas remplacer le shebang par#!/bin/sh
car bash s'exécutera en mode POSIX de sorte que certains de vos scripts pourraient se comporter différemment. -
Si vous écrivez portable scripts, c'est à dire des scripts en utilisant uniquement les utilitaires POSIX et leurs options supportées, vous pouvez continuer à utiliser
#!/bin/sh
sur votre "système (c'est-à-dire un système où/bin/sh
est un shell POSIX). -
Il vous écrivez strictement conforme POSIX scripts pour être distribués dans les différentes plates-formes et vous êtes sûr qu'ils ne seront lancées à partir d'un POSIX système, vous pouvez et probablement supprimer le shebang comme indiqué dans la norme POSIX standard:
la raison d'être est que la norme POSIX n'exige pas que /bin/sh
soit le shell compatible POSIX, de sorte qu'il n'existe aucun moyen portable de spécifier son chemin dans un shebang. Dans ce troisième cas, pour pouvoir utiliser la syntaxe 'find-exec' sur des systèmes incapables d'exécuter un still sans shebang script exécutable, Vous pouvez simplement spécifier l'interpréteur dans la commande find elle-même, par exemple:
find /tmp -name "*.foo" -exec sh -c 'myscript "$@"' sh {} +
ici, comme sh
est spécifié sans chemin, le shell POSIX sera lancé.
l'en-tête est utile car il spécifie quel shell utiliser lors de l'exécution du script. Par exemple, #!/bin/zsh
changerait le shell en zsh au lieu de bash, où vous pouvez utiliser différentes commandes.
par exemple, cette page indique ce qui suit:
à l'Aide de #!/ bin / sh, le Bourne shell par défaut dans la plupart des variantes commerciales D'UNIX, rend le script portable à des machines non-Linux, bien que vous caractéristiques spécifiques de sacrifice Bash ...
$SHELL et #!/bin/bash #ou!/bin/sh sont différents.
Pour commencer, #!/ bin /sh est un lien symbolique vers/bin /bash sur la plupart des systèmes Linux (sur Ubuntu, il est maintenant/bin / dash)
mais sur la question de savoir s'il faut commencer par /bin/sh Ou /bin/bash:
Bash et sh sont deux coquillages différents. Fondamentalement bash is sh, avec plus des fonctionnalités et une meilleure syntaxe. La plupart des commandes fonctionnent de la même, mais ils sont différent.
supposez simplement que si vous écrivez un script bash, collez avec /bin/bash et pas /sh car des problèmes peuvent survenir.
$ SHELL ne reflète pas nécessairement le shell en cours d'exécution. Au lieu de cela, $SHELL est le shell préféré de l'utilisateur, qui est typiquement le un ensemble dans /etc / passwd. Si vous démarrez un shell différent après la journalisation dans, vous ne pouvez pas nécessairement vous attendre à ce que $SHELL corresponde au shell actuel. plus.
This est à moi par exemple, mais il peut aussi être /root:/bin/dash ou /root:/bin/sh selon le shell que vous avez entré dans passwd. Pour éviter tout problème, conservez le fichier passwd dans /bin / bash et utilisez $SHELL vs. #!/ bin / bash n'aurait pas autant d'importance.
root@kali:~/Desktop# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
Sources: http://shebang.brandonmintern.com/bourne-is-not-bash-or-read-echo-and-backslash / https://unix.stackexchange.com/questions/43499/difference-between-echo-shell-and-which-bash http://man.cx/sh http://man.cx/bash
en plus de ce que les autres ont dit, le shebang permet également la mise en évidence de la syntaxe dans certains éditeurs de texte, par exemple vim.