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
26
demandé sur Steven Penny 2014-08-06 20:48:04

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

Linux page de manuel de :

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 .

33
répondu Roland Smith 2015-10-28 13:22:33
Les Scripts

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.

13
répondu Barmar 2014-08-06 16:52:05

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

3
répondu jrjc 2014-08-12 16:02:21
  • 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:

en l'état, une demande strictement conforme ne doit pas utiliser"#!"dans les deux premiers caractères du fichier.

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é.

3
répondu jlliagre 2014-11-10 07:38:53

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 ...

1
répondu pyrrhic 2014-08-06 16:52:53

$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

0
répondu Chirality 2017-04-13 12:36:30

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.

0
répondu Konrad Höffner 2017-05-09 07:44:10