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

Dans la plupart des scripts shell j'ai vu (en plus de ceux que je n'ai pas écrit moi-même), j'ai remarqué que le shebang est mis à #!/bin/sh . Cela ne me surprend pas vraiment sur les scripts plus anciens, mais il existe aussi sur de nouveaux scripts.

Y a-t-il une raison pour préférer /bin/sh over /bin/bash , puisque bash est largement omniprésent et souvent par défaut sur beaucoup de machines Linux et BSD depuis plus d'une décennie?

  1. Il y a des systèmes qui n'exportent pas bash par défaut (par exemple FreeBSD).
  2. Même si bash est installé, il se peut qu'il ne soit pas situé dans /bin .
  3. La plupart des scripts simples n'exigent pas de bash.
  4. L'utilisation du shell POSIX est plus portable et les scripts s'exécuteront sur une plus grande variété de systèmes.

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

  • Vitesse du système. Un code plus petit de tableau de bord se charge plus rapidement et s'exécute aussi plus rapidement. Avec un peu (petit?) Effort supplémentaire (coût) pour les programmeurs de scripts shell.

  • Sécurité. La diversité des coquilles aide à résister aux insectes. Les systèmes Debian n'étaient généralement pas vulnérables à shellshock car le shell par défaut n'avait pas une telle vulnérabilité.

Bash est en effet le shell par défaut pour les users , comme c'est plus puissant et a beaucoup plus d'éléments pour faciliter le encoding. C'est aussi le sh par défaut dans Mac OS (celui lié à / bin / sh). Cependant, appeler bash avec le nom de lien de sh fait commencer comme un shell posix conforme.

D'autres ont fait remarquer que les prémisses de la question, à savoir que la shell Bourne Again est par défaut et omniprésente, sont carrément fausses.

En plus de cela, il y a en effet de bonnes raisons d'utiliser autre chose que le shell Bourne Again pour interpréter les scripts shell. Ces raisons ont motivé le grand projet d'Ubuntu et de Debian pour éliminer les bashismes et faire exécuter autant de scripts shell par l'initialisation du système (qui était beaucoup de scripts shell avec System 5 rc ) le shell Debian Almquist au lieu du shell Bourne Again.

Autrement dit: le shell Bourne Again, rempli de fonctionnalités interactives, n'est pas l'interpréteur de shell le plus rapide pour un script shell conforme à POSIX. Donc, si l'on peut rendre ses scripts shell POSIX conforms, en les interprétant avec un programme plus léger, comme le shell Debian Almquist, son système fonctionnera mieux. (En fin de count, Debian a dû apporter de légers ajustements à la coquille d'Almquist, pour append le support de quelques constructions de coquilles non-POSIX qui étaient simplement trop profondément et largement embeddedes et trop utiles pour s'en débarrasser).

Le résultat de tout cela était un gain important dans la performance bootstrap.

Il y a donc deux classs distinctes de shell à considérer, ici:

  • Les coquilles avec toutes les fonctions interactives flashy, qui sont configurés comme coquilles de connection interactives pour les users dans la database des counts.
  • Les shells qui interprètent rapidement de nombreux scripts, qui sont utilisés comme interpréteurs de script par les programmes de script shell.

Notez que parler de ceci comme "préférant /bin/sh " est trop simplificateur. Debian avait au less deux objectives:

  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 et d'autres comme /bin/sh , il y avait soit …

    1. … rendant les scripts aussi portables que possible, de sorte que la commutation de /bin/sh mappée n'a pas brisé les choses; ou

    2. … faire en sorte que les scripts non portables ciblent explicitement le programme d'interprétation correct , au lieu de simplement s'attendre à ce que /bin/sh mappe.

  2. Le shell Debian Almquist était le mappage par défaut de /bin/sh au lieu du Bourne Shell, de sorte que les scripts qui étaient conforms à POSIX (ou, plus proprement, Debian Policy Manual) s'exécutaient plus rapidement.

Et bien sûr, une fois que l'on y arrive, on peut le prendre beaucoup plus loin; telles que les compromis d'efficacité de /bin/true et /usr/bin/clear étant 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 tournant du siècle, j'ai écrit et publié un interpréteur en command line, à la fois interactif et non interactif, expliquant cette même division dans son doco et notant la différence entre les variables d'environnement COMSPEC et OS2_SHELL . De la même manière, la discussion sur la suppression des bashismes dans les scripts d'installation / suppression du système V rc de Debian remonte aux années 1990.

Plus de lecture

  • https://superuser.com/a/696310/38062
  • https://unix.stackexchange.com/a/193210/5132
  • tiret comme /bin/sh . Ubuntu wiki.
  • tiret comme /bin/sh . Wiki Debian.
  • bashismes . Le wiki de Greg.
  • Brian M. Carlson (2005-07-29). Annonce de service public concernant la politique 10.4 . <1122626433.30217.39.camel@stonewall.crustytoothpaste.ath.cx>. debian-devel.
  • Raphaël Geissert (2009-04-12). tiret par défaut / bin / sh et RGs d'archivage sans bashisms . <200904121359.09387.atomo64@gmail.com> debian-devel.
  • debian-policy: veuillez ne pas déclarer que les scripts fonctionnant sous le tiret sont «probablement» conforms à la politique . Bogue Debian n ° 490604.
  • Rapport sur le package Debian pour le tiret d'objective
  • debian-policy: découragez l'utilisation de echo -n, et echo en général . Bogue Debian n ° 490605.
  • Rebecca Sobol (2009-07-29). Un conte de deux coquillages: bash ou tiret . LWN.
  • Justus Pendleton (1997-04-22). bash-isms dans les packages . <E0wJjkL-0001II-00@ryoohki.res.cmu.edu>. debian-devel.
  • Jonathan de Boyne Pollard (2000). "Frontaux d'interpréteur de commands" . Référence de command Command Interpreter . Documentation en ligne pour l'interpréteur de commands 32 bits.
  • John Chambers (1990). La command / bin / true Command et Copyright

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

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

Que dois-je utiliser dans mon shebang?

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

Sur mon système (Centos 6.6), sh est lié à bash :

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

Cela signifie que j'utilise toujours #!/bin/bash dans mon script, sauf si j'ai vérifié que je n'ai pas de bashims dans mon script.

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

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

Voici un exemple de script qui se comportera incorrectement en fonction de l'implémentation sh utilisée par le système:

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

Lors de l'utilisation de bash le script imprimera:

 2 

Lorsque vous utilisez le dash le script imprimera:

 1 

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

  • Vérifiez le script avec checkbashisms – Notez que cela ne finda pas tous les bashims. Il n'a pas trouvé le bashisme dans mon script ci-dessus
  • Testez le script en utilisant une autre implémentation sh . Je teste habituellement avec un dash , mais je m'attends à ce que certains bashismes ou dashims puissent encore passer à travers.

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

La seule raison qui rest d'é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 set de logiciels installés inconnu est plus importante que tout autre facteur .

/bin/sh est le seul et unique interpréteur de script disponible sur tout ce qui s'appelle Unix. Mais sur un très grand nombre de systèmes existants, /bin/sh et les utilitaires associés ne sont même pas compatibles avec la spécification "shell and utilities" de POSIX.1-1996, sans parler de quelque chose de plus moderne. Les outils standard sont un module optionnel, installé dans /usr/xpg4 ou dans un tel location non-évident. 1 Le scripting au langage shell de sous-set portable est encore plus fastidieux et plus sujet aux erreurs que le scripting au langage shell POSIX. (Lire à travers un script de configure généré par Autoconf parfois si vous ne me croyez pas. Juste la configuration devrait être suffisante pour vous convaincre.)

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

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

1 Par exemple, Solaris 10 et plus ancien ont envoyé le shell Bourne d'origine sous /bin/sh . Je suis informé que Solaris 11 l'a mis à jour en ksh93.

Vous devriez en fait utiliser soit

 #! /bin/env sh 

ou

 #! /bin/env bash 

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

Pour être très sûr ( par exemple dans le cas de redémarrages mono-user), utilisez sh sinon utilisez bash .