web-dev-qa-db-fra.com

Quand dois-je utiliser #!/Bin/bash et quand #!/Bin/sh?

Quand #!/bin/bash est-il plus approprié que #!/bin/sh dans un script Shell?

101
Hendré

En bref:

  • Plusieurs shells implémentent un sur-ensemble de la spécification POSIX sh . /bin/sh pourrait être un lien vers ash, bash, dash, ksh, zsh, etc. (Ce sera toujours compatible avec sh - jamais csh ni poisson.)

  • Tant que vous vous en tenez aux seules caractéristiques sh, vous pouvez (et même probablement devriez) utiliser #!/bin/sh et le script devrait fonctionner correctement, quel que soit le shell utilisé.

  • Si vous commencez à utiliser des fonctionnalités spécifiques à bash (par exemple, des tableaux), vous devez spécifiquement demander bash car, même si /bin/sh appelle déjà bash sur le système votre, il se peut que ce ne soit pas le cas sur le système de tous les autres. et votre script ne sera pas exécuté là-bas. (Il en va de même pour zsh et ksh.) Vous pouvez utiliser shellcheck pour identifier les bashismes.

  • Même si le script est destiné uniquement à un usage personnel, vous remarquerez peut-être que certains systèmes d'exploitation changent /bin/sh au cours des mises à niveau - par exemple, sur Debian, c'était bash, mais plus tard, il a été remplacé par un tiret minimal. Des scripts qui utilisaient des bashismes mais avaient #!/bin/sh soudainement éclaté.

Toutefois:

  • Même #!/bin/bash n'est pas très correct. Sur différents systèmes, bash peut vivre dans /usr/bin ou /usr/pkg/bin ou /usr/local/bin.

  • Une option plus fiable est#!/usr/bin/env bash, qui utilise $ PATH. (Bien que l'outil env ne soit lui-même pas strictement garanti, /usr/bin/env fonctionne toujours sur plus de systèmes que /bin/bash.)

147
grawity

Utilisez le Shebang correspondant au shell que vous avez réellement utilisé pour développer et déboguer votre script. C'est à dire. Si votre shell de connexion est bash et que vous exécutez votre script en tant qu'exécutable dans votre terminal, utilisez #!/bin/bash. Ne supposez pas simplement que, puisque vous n'avez pas utilisé de tableaux (ou de toute fonction bash dont vous avez connaissance), vous êtes sûr de choisir le shell de votre choix. Il existe de nombreuses différences subtiles entre les shells (echo, fonctions, boucles, etc.) qui ne peuvent pas être découvertes sans un test approprié.

Considérez ceci: si vous quittez #!/bin/bash et que vos utilisateurs ne l’ont pas, ils verront un message d’erreur clair, quelque chose comme:

Error: /bin/bash not found

La plupart des utilisateurs peuvent résoudre ce problème en moins d'une minute en installant le package approprié. D'autre part, si vous remplacez Shebang par #!/bin/sh et le testez sur un système où /bin/sh est un lien symbolique vers /bin/bash, vos utilisateurs qui n'ont pas bash seront en difficulté. Ils verront probablement un message d'erreur cryptique du type:

Error in script.sh line 123: error parsing token xyz

Cela peut prendre des heures à résoudre, et il n'y aura aucune idée de quel Shell ils auraient dû utiliser.

Il n'y a pas beaucoup de raisons pour lesquelles vous voudriez utiliser un autre shell dans le Shebang. L'une des raisons est que le shell que vous avez utilisé n'est pas répandu. Une autre solution consiste à améliorer les performances avec sh, qui est nettement plus rapide sur certains systèmes, ET votre script créera un goulot d'étranglement en termes de performances. Dans ce cas, testez minutieusement votre script avec le shell cible, puis modifiez le Shebang.

18
Dmitry Grigoryev

Vous ne devriez jamais utiliser que #! /bin/sh.

Vous ne devriez jamais utiliser d'extensions bash (ou zsh, ou fish, ou ...) dans un script Shell.

Vous ne devriez jamais écrire que des scripts Shell fonctionnant avec anyimplémentation du langage Shell (y compris tous les programmes "utilitaires" associés au Shell lui-même). Ces jours-ci, vous pouvez probablementprendre POSIX .1-2001 ( not -2008) faisant autorité pour ce que Shell et les utilitaires sont capables de faire, mais sachez que vous pourrez un jour être amené à porter votre script vers un système hérité (par exemple Solaris ou AIX) dont Shell et les utilitaires ont été gelés vers 1992.

Quoi, sérieusement?!

Oui, vraiment.

Voici le problème: Shell est un terriblelangage de programmation). Son seul objectif est que /bin/sh est le seul et unique interprète de script que chaque installationest garantie d'avoir.

Voici l’autre chose: une itération de l’interpréteur principal de Perl 5 (/usr/bin/Perl) correspond à plussusceptible d’être disponible sur une installation Unix sélectionnée de manière aléatoire que (/(usr|opt)(/(local|sfw|pkg)?)?/bin/bash. Autres bons langages de script (Python, Ruby, node.js, etc.). - Je vais même inclure PHP et Tcl dans cette catégorie lorsqu’on le compare à Shell) sont aussi approximativement disponibles que bash et d’autres shells étendus.

Par conséquent, si vous avez la possibilité d'écrire un script bash, vous avez la possibilité d'utiliser un langage de programmation qui n'est pas terrible, à la place.

Maintenant, simplesscripts Shell, ceux qui exécutent simplement quelques programmes dans une séquence à partir d’un travail cron ou autre, il n’ya rien de mal à les laisser en tant que scripts Shell. Mais les scripts Shell simples n’ont pas besoin de tableaux ni de fonctions [[ même. Et vous ne devriez écrire que des scripts compliquésShell lorsque vous n'avez pas d'autre choix. Les scripts Autoconf, par exemple, sont toujours des scripts Shell. Mais ces scripts doivent être exécutés sur chaqueincarnation. de /bin/sh qui est pertinent pour le programme en cours de configuration et qui signifie qu’ils ne peuvent utiliser aucune extension. Vous n’avez probablement pas à vous soucier des anciens Unix propriétaires, mais vous devez probablement devriezvous soucier des BSD actuels à code ouvert, certains d'entre eux n'installe pas bash par défaut, et des environnements intégrés qui ne vous donnent qu'un shell minimal et busybox.

En conclusion, au moment où vous vous trouvez vouloirune fonctionnalité qui n’est pas disponible dans le langage Shell portable, c’est le signe que le script est devenu trop compliqué pour rester un script Shell. Réécrivez-le dans un meilleur langage.

6
zwol

Généralement, si le temps est plus important que la fonctionnalité, vous utiliserez le shell le plus rapide. sh est souvent associé à dash et a tendance à être utilisé pour les tâches cron de root ou les opérations de traitement par lots où chaque (nano) seconde compte.

4
mckenzm

Pour être encore plus bref, utilisez sh si la portabilité sur la plupart des systèmes est primordial et bash si vous souhaitez utiliser certaines de ses fonctionnalités spécifiques, telles que les tableaux, si la version de bash le prend en charge.

3
Spencer Williams
  • sh (dans la plupart des cas), bash si requis (ou ksh, ou autre)

Le chemin le plus sûr. Quand cela est codé en dur, cela devrait être/usr/bin/shellOfChoice mais une nouvelle convention que j'essaie d'utiliser toujours maintenant - comme "emplacements par défaut" via un changement, PATH peut changer:

#!/usr/bin/env sh ou
#!/usr/bin/env bash
ou par exemple, les scripts Perl
#!/usr/bin/env Perl -w

Bien sûr, lorsque vous avez une raison pour qu'un script prenne JAMAIS automatiquement un nouveau PATH, continuez à le coder en dur - et ensuite,/usr/bin/quelque chose devrait être le chemin le plus susceptible d'être utilisé.

1
Michael Felt