Y a-t-il une raison d'avoir un shebang pointant vers / bin / sh plutôt que / bin / bash?

53

Dans la plupart des scripts shell que j'ai vus (à part ceux que je n'ai pas écrits moi-même), j'ai remarqué que le shebang est réglé sur #!/bin/sh. Cela ne me surprend pas vraiment sur les anciens scripts, mais il existe aussi sur des scripts relativement nouveaux.

Y at - il raison de préférer /bin/shplus /bin/bash, depuis bashest à peu près partout, et souvent par défaut, sur de nombreuses machines Linux et BSD , depuis plus d' une décennie?

Jules
la source
23
C'est un bon partice à utiliser /bin/shsi vous n'utilisez pas de bashfonctions spécifiques . Un jour, vous pourriez être amené à utiliser l'un de vos scripts sur un système sur lequel il n'est pas installé (serveur distant, ordinateur embarqué ...)
Mathieu
1
en général, vous devriez éviter de poser des questions qui se prêtent à des réponses fondées sur des opinions (ce qui est la seule façon possible de répondre à cette question, mais c’est tout simplement mon opinion ) .
mikeserv
9
Je pense qu'il est possible de répondre à cette question sans faire appel à une simple opinion, en indiquant au moins deux organisations qui traitent ce problème depuis plusieurs années et en examinant l'historique et les résultats. Avec beaucoup de lectures supplémentaires attachées, pour démarrer. ☺
JdeBP
3
@JulesMazur ...the answers so far are fairly subjective...Un énoncé "subjectif" est essentiellement basé sur une opinion par définition. /bin/bashne devrait être utilisé que lorsque bash est explicitement requis. En tant que développeur, bien avant 40 ans bash, je n'en avais presque jamais explicitement eu besoin, sauf lors de tests. (Je m'efforce également d'éviter les extensions de shell, mais la plupart de mes scripts sont destinés à la distribution.) De nombreux scripts sur le net devraient également être destinés à une utilisation étendue.
user2338816
2
@ user2338816 mon mauvais, je voulais dire objectif . Merci pour vos points!
Jules

Réponses:

84
  1. Il existe des systèmes ne livrant pas bash par défaut (par exemple, FreeBSD).
  2. Même si bash est installé, il se peut qu'il ne se trouve pas dans /bin.
  3. La plupart des scripts simples ne nécessitent pas bash.
  4. L'utilisation du shell POSIX est plus portable et les scripts s'exécutent sur une plus grande variété de systèmes.
Marco
la source
17
Une autre raison: souvent / bin / sh est plus rapide que bash, ou du moins se charge plus vite (en raison de sa taille plus petite).
derobert
5
@derobert, /bin/shest plus rapide si ce n'est pas bash, il y a encore quelques systèmes comme OS / X ou RHEL où /bin/shest bash.
Stéphane Chazelas
1
Certains OS le lient, car bash est compatible avec les versions antérieures.
Sobrique
7
Quelques scripts supposent que /bin/shc'est le cas /bin/bash. Ubuntu passant de bash à dash les a tous brisés.
Atamanroman
19
@atamanroman: Les scripts étaient incorrects en premier lieu, ils auraient dû les utiliser #!/bin/bashs'ils voulaient Bash (rien à redire à ça!). Le changement a été principalement effectué en amont dans Debian. Cela a amélioré l'expérience utilisateur et a eu un impact mesurable sur le temps de démarrage du système. Cela a également eu un impact positif sur la sécurité, voir "Shellshock".
Dietrich Epp
28

La plupart des scripts système sous Linux (liés à Debian: Ubuntu, Mint, etc.) sont écrits pour s'exécuter dans le tiret plus rapide, qui est la valeur par défaut / bin / sh sur ces systèmes. La raison est double:

  • Vitesse du système Un code plus petit de tirets se charge plus rapidement et est également plus rapide. Avec quelques (petits?) Efforts supplémentaires (coûts) pour les programmeurs de scripts shell.

  • Sécurité. Avoir une diversité de coques aide à la résilience aux bugs. Les systèmes Debian n'étaient généralement pas vulnérables à shellshock car le shell par défaut ne présentait pas une telle vulnérabilité.

Bash est en effet le shell par défaut pour les utilisateurs , car il est plus puissant et contient beaucoup plus d’éléments pour faciliter le codage. C'est également la valeur shpar défaut sous Mac OS (celle liée à / bin / sh). Cependant, appeler bashavec le nom du lien le shfait démarrer comme un shell conforme à posix.


la source
2
Un ensemble plus limité d'outils disponibles d'un shell plus simple rend l'écriture de code plus difficile (évitez toute guerre fanatique sur ce sujet). C'est pourquoi certains utilisateurs aiment zsh, qui dispose de davantage d'outils que bash. J'aime plus Bash, de même qu'un équilibre entre les deux extrêmes.
4
@RobertL, de nombreuses fonctionnalités ajoutées à ksh et adoptées par bash existent parce qu'elles facilitent considérablement le processus d'écriture de scripts robustes et corrects. Sans les divers ajouts permettant, par exemple, d'effectuer une assignation et une évaluation indirectes en toute sécurité, on peut se retrouver en train d'utiliser eval, avec un risque de sécurité inhérent; de même, sans prise en charge intégrée des expressions rationnelles, il peut être nécessaire d'utiliser des commandes externes (avec une lourde pénalité de performance) pour faire correspondre même sur une seule ligne, etc.
Charles Duffy
1
@RuiFRibeiro, rien n'est statiquement lié dans Debian. Dash est plus limité, mais principalement dans les fonctionnalités interactives (pas de complétion, etc.), de sorte qu'il est plus rapide pour les scripts.
Jan Hudec
21

D'autres ont souligné que les prémisses de la question, à savoir que le shell Bourne Again est un défaut et omniprésent, sont carrément fausses.

En plus de cela, il existe effectivement de bonnes raisons d'utiliser autre chose que le shell Bourne Again pour interpréter les scripts shell. Ces raisons motivées grand projet de Ubuntu et Debian, sur plusieurs années, pour éliminer bashismes et de faire autant de scripts shell exécutés par l' initialisation du système (qui était beaucoup de scripts shell avec le système 5 rc) et l' installation de paquets / utilisation de l' élimination de la Le shell Debian Almquist au lieu du shell Bourne Again.

Autrement dit, le shell Bourne Again, riche en fonctionnalités interactives, n’est pas l’interpréteur de shell le plus rapide pour un script shell conforme à POSIX. Donc, si on peut créer des scripts shell conformes à POSIX, en les interprétant avec un programme plus léger, comme le shell Debian Almquist, son système fonctionnera mieux. (En fin de compte, Debian a dû apporter de légers ajustements au shell Almquist, pour ajouter un support pour quelques constructions de shell non POSIX qui étaient simplement trop profondes et trop intégrées et trop utiles pour s'en débarrasser.)

Le résultat de tout cela a été un gain majeur en performances de bootstrap.

Donc, il y a deux classes distinctes de shell à considérer, ici:

  • Les shells avec toutes les fonctionnalités interactives flashy, qui sont configurés en tant que shells de connexion interactifs pour les utilisateurs dans la base de données de comptes.
  • Les shells qui interprètent rapidement un grand nombre de scripts, qui sont utilisés comme interpréteurs de script par les programmes de script shell.

Notez que parler de cela comme "préférer /bin/sh" est une simplification excessive. Debian avait en fait au moins deux objectifs:

  1. Face aux administrateurs utilisant le shell Debian Almquist, le shell Z (en mode POSIX), le shell Bourne Again (en mode POSIX), le shell MirBSD Korn, etc. /bin/sh, il y avait soit…

    1. … Rendre les scripts aussi portables que possible, de sorte que le basculement vers ce qui a été /bin/shmappé ne casse pas les choses; ou

    2. … Faire des scripts non portables cibler explicitement le bon programme d'interprétation , au lieu d'attendre simplement cette /bin/shcarte.

  2. Il y avait fait la Debian Almquist shell le mappage par défaut pour la /bin/shplace de la Bourne Shell, de sorte que ces scripts étaient compatible POSIX (ou, plus correctement, Debian Policy Manual conforme) ont couru plus vite.

Et bien sûr, une fois que l’on s’y prend, on peut aller beaucoup plus loin; tels que la prise en compte des compromis d'efficacité de ceux qui aiment /bin/trueet /usr/bin/clearêtre des scripts shell ou des programmes compilés. Mais cela dépasse le cadre de cette réponse, heureusement. ☺

Rien de tout cela n'est très nouveau, ni même spécifique à Unix, bien sûr. Avant le début du siècle, j’écrivais et publiais un interpréteur de ligne de commande disponible en versions "interactive" et "non-interactive", expliquant cette division même dans son document et notant la différence entre les variables d’environnement COMSPECet OS2_SHELL. De même, la discussion sur la suppression des basismes dans le System V de Debian rcet les scripts d'installation / de suppression de paquets remonte aux années 1990.

Lectures complémentaires

JdeBP
la source
2
"En fin de compte, Debian a dû apporter de légers ajustements au shell Almquist, afin de prendre en charge deux constructions de shell non-POSIX qui étaient simplement trop profondes et trop intégrées et trop utiles pour être supprimées." - Lequel de vos nombreux liens contient des informations à ce sujet? Cela semble très intéressant. :)
Wildcard
3
IMHO, la performance n'est qu'un facteur de motivation pour amener les gens à accepter les changements. La principale raison initiale de ce changement est que bash a continué d’inverser la compatibilité ascendante. J'ai personnellement eu à résoudre des problèmes de bash au moins 3 fois dans ma carrière car le script fonctionnait dans une version de bash mais échouait dans une autre (se produit généralement après la mise à niveau du système d'exploitation). Dash n'est pas simplement un interprète un peu plus rapide. Il est également beaucoup plus stable en termes de comportement.
Slebetman
Je serais intéressé de savoir si les commentaires dans la Schily Bourne Shellpage de manuel, voir schilytools.sourceforge.net/bosh.html sont appropriés pour permettre aux gens de comprendre comment écrire un script portable (cela ne dépend que Bourne Shell featuresde 1989). Ce que j'ai fait, c'est mentionner toutes les améliorations qui ne sont pas dans les vieux Bourne Shells. BTW: Je suis également intéressé à connaître une liste de bashismes en dash.
Schily
8

Y a-t-il une raison d'avoir un shebang pointant vers / bin / sh plutôt que / bin / bash?

Oui. @ L'excellente réponse de Marco le décrit bien.

Que devrais-je utiliser dans mon shebang?

Lorsque vous écrivez vos propres scripts, vous devriez indiquer au shebang la chose la plus générale que vous avez testée.

Sur mon système (Centos 6.6), shest lié symboliquement à bash:

$ ls -l /bin/sh 
lrwxrwxrwx 1 root root 4 Dec  2  2014 /bin/sh -> bash

Cela signifie que je l'utilise toujours #!/bin/bashdans mon shebang à moins d'avoir vérifié que je n'ai pas de bashims dans mon script.

En définissant le shebang sur #!/bin/shvous, vous promettez que le script fonctionnera avec toutes les implémentations de sh.

C'est une promesse beaucoup plus grande que de dire que le script fonctionnera avec bash.

Voici un exemple de script qui se comportera de manière incorrecte en fonction de l' shimplémentation utilisée par le système:

#!/bin/sh
n=1
a=$((++n))
echo $n

Lors de l'utilisation bashdu script imprimera:

2

Lors de l'utilisation dashdu script imprimera:

1

Si je veux utiliser #!/bin/shque dois-je faire?

  • Vérifiez le script avec checkbashisms- Notez que cela ne trouvera pas tous les bashims. Il n'a pas trouvé le bashisme dans mon script ci-dessus
  • Testez le script en utilisant une autre shimplémentation. Je teste généralement avec dash, mais je pense que certains bashismes ou dashims peuvent toujours passer à travers.

La page DashAsBinSh sur le wiki Ubuntu contient de nombreuses informations intéressantes.

soixantefootersdude
la source
6
"Lorsque vous écrivez vos propres scripts, vous devez indiquer au shebang la chose la plus générale contre laquelle vous avez testé ... En réglant le shebang sur #! / Bin / sh, vous promettez que le script fonctionnera avec toutes les implémentations de sh . " Excellent point. +1, et vous m'avez fait repenser la façon dont j'écrirai mes shebangs pour l'avenir. Je vous remercie! :)
Wildcard
2
Eh bien, pas toutes les implémentations de /bin/sh; juste ceux compatibles POSIX.
Blacklight Shining
4

La seule raison qui reste pour écrire un script shell, au lieu d'un script dans un langage plus puissant et ergonomique, est si la portabilité vers des systèmes hérités avec un ensemble inconnu de logiciels installés est plus importante que tout autre facteur .

/bin/shest le seul et unique interprète de script disponible sur tout ce qui s'appelle Unix. Mais sur un grand nombre de systèmes hérités, /bin/shet les utilitaires associés ne sont même pas conformes à la spécification "shell and utilities" de POSIX.1-1996, sans parler de quelque chose de plus moderne. Les outils conformes aux normes sont un complément optionnel, installé dans /usr/xpg4ou dans un tel lieu non évident. 1 La génération de scripts dans le langage shell de sous-ensembles portable est encore plus fastidieuse et sujette aux erreurs que celle de scripts dans le langage shell POSIX. (Lisez un configurescript généré par Autoconf si vous ne me croyez pas. La configuration devrait suffire à vous convaincre.)

Mais si vous pouvez supposer qu'un autre interpréteur de script est installé (par exemple, Bash), vous pouvez alors supposer qu'un interprète est installé pour un meilleur langage de script . Perl, par exemple, a plus de chances d’être disponible que Bash.

Par conséquent, vous ne devriez jamais écrire de #! /bin/bashscript, car si c'est une option, une meilleure langue est également une option.

1 Par exemple, Solaris 10 et versions antérieures ont fourni le shell Bourne d'origine en tant que /bin/sh. Je suis informé que Solaris 11 l'a mis à jour vers ksh93.

zwol
la source
3
Dans quelle langue allez-vous écrire un script pour démarrer un système? Ou à l'intérieur d'un routeur SOHO (systèmes embebed limités)? Ou sous Android? Un shell sera disponible dans tous ces cas. Perl pas.
1
Il y a des inexactitudes dans les parties de votre réponse relatives à Solaris. Sous Solaris 10 et versions antérieures, POSIX.1-1996 /bin/shn'est pas un shell Bourne original de syntaxe antérieure à POSIX. Cela fait #!/bin/shun très mauvais shebang pour les scripts à exécuter avec ces versions. Les scripts portables sur Solaris utiliseraient, #!/usr/xpg4/bin/shce qui ne sera pas très portable sur d'autres systèmes d'exploitation. Sur la dernière version de Solaris, Oracle Solaris 11, première version 2011, /bin/shest un système moderne ksh93conforme aux spécifications POSIX les plus récentes et doté de nombreuses extensions modernes.
jlliagre
1
@BinaryZebra: "Un shell" sera disponible, oui. Mais bash n’est pas nécessairement ce shell (en particulier la plupart des routeurs SOHO ashqui sont fournis avec busybox), et j’ai tendance à penser que zwol a raison de dire que perl est plus communément disponible que bash.
Ben Voigt
1
@ BenVoigt Je commente cette phrase "La dernière raison d'écrire un script shell". Il y a encore des cas qui nécessitent un shell pour certaines tâches (pas toutes). C'étaient quelques exemples du haut de ma tête. OTOH Dans les systèmes avec suffisamment de mémoire (presque tous dans les normes actuelles) et assez de puissance, installer Perl (ou Python, ou ....) est assez rapide et facile. Cependant, je ne préconise aucun shell spécifique. Où lisez-vous cela dans mon commentaire?
2
Tout à fait en désaccord avec votre affirmation hautement factuelle et non factuelle selon laquelle "si elle bashest disponible, le langage est meilleur, vous ne devriez donc jamais écrire de bashcode." En outre, comme le fait remarquer @sixtyfootersdude, vous devez toujours utiliser #!/bin/bashsauf si vous avez vérifié que votre script fonctionne avec n'importe quel shell POSIX.
Wildcard
0

Vous devriez réellement utiliser soit

#! /bin/env sh

ou

#! /bin/env bash

De cette façon, vous appelez l’un ou l’autre shell par la manière dont ils sont installés sur ce système.

Pour être très sûr ( par exemple, en cas de redémarrage par un utilisateur unique), utilisez shsinon bash.

Paul Evans
la source
6
De cette réponse : the advantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH. The disadvantage of #!/usr/bin/env python is that it will use whatever python executable appears first in the user's $PATH.Cela s'applique probablement aussi à shet bash.
Jules
12
Non, vous ne devez rien utiliser #!/bin/envdans un script portable. Il est parfaitement raisonnable de supposer qu’il /bin/shexiste un shell fonctionnant conformément à POSIX. D'autre part, aucun de mes systèmes n'a un /bin/env.
Blacklight Shining
Aussi un bon point.
Jules
1
@Blacklight Shining, il est tout à fait faux de supposer un shell compatible POSIX /bin/sh. POSIX n'en a pas besoin et définit plutôt d'autres règles pour obtenir un environnement compatible POSIX sur une plate-forme certifiée POSIX.
Schily
4
/usr/bin/envpas universellement disponible ...
vonbrand