Quand est-il #!/bin/bash
plus approprié que #!/bin/sh
dans un script shell?
linux
shell-script
Hendré
la source
la source
bash
fonctions et une syntaxe plutôt que dessh
fonctions et une syntaxe.vim
celabash
mettrait en évidence des -ismes si votre script a le#!/bin/sh
shebang. Je ne le change quebash
si les choses deviennent trop poilues pour que les fonctionnalités bash soient nécessaires.$(...)
est particulièrement odieux. En outre, certains d'entre eux sont subtils [<(...)
etcmd >& file
n'obtiennent aucune erreur en surbrillance, par exemple, ils n'ont tout simplement pas de surbrillance spéciale pour ce qu'ils veulent dire, avec ou sansg:is_bash
]Réponses:
En bref:
Plusieurs shells implémentent un sur-ensemble de la spécification POSIX sh . Sur différents systèmes,
/bin/sh
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
sh
uniquement aux fonctionnalités, vous pouvez (et même probablement le devriez) utiliser#!/bin/sh
et le script devrait fonctionner correctement, quel que soit son shell.Si vous commencez à utiliser des fonctionnalités spécifiques à bash (par exemple, des tableaux), vous devez spécifiquement demander bash, car même s'il
/bin/sh
appelle déjà bash sur votre système, il se peut que ce ne soit pas le cas du système de tous les autres et que votre script n'y soit pas exécuté. (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
lors des mises à niveau. Par exemple, sous Debian, il s’agissait de bash, mais a été remplacé plus tard par un tiret très minimal. Des scripts qui utilisaient des bashismes mais qui s'étaient#!/bin/sh
soudainement cassés.Pourtant:
Même
#!/bin/bash
n'est pas très correct. Sur des systèmes différents, bash peut vivre dans/usr/bin
ou/usr/pkg/bin
ou/usr/local/bin
.Une option plus fiable consiste à
#!/usr/bin/env bash
utiliser $ PATH. (Bien que l'env
outil lui-même ne soit pas strictement garanti non plus,/usr/bin/env
il fonctionne toujours sur plus de systèmes que lui/bin/bash
.)la source
/bin/sh
là, il essaiera d’imiter lessh
fonctionnalités (voir la page de manuel ), ne sachant pas que des fonctionnalités spécifiques à Bash sont disponibles dans ce mode.env
outil est un outil posix qu'il devrait être trouvé dans la plupart des distributions, mais je ne suis pas sûr que certains puissent ne pas respecter posix./bin
: " Les applications doivent noter que le PATH standard du shell ne peut pas être supposé être / bin / sh ou / usr / bin / sh, et doit être déterminé par interrogation du chemin PATH renvoyé par getconf PATH, en s'assurant que le chemin renvoyé est un chemin absolu et non un shell intégré ". Voir aussi cette question et plus précisément cette réponse .#!
fonctionner les scripts?echo foo ^ cat
émetfoo ^ cat
dans POSIX sh et n’émet quefoo
dans Bourne (comme^
un caractère de canal là-bas).Utilisez le shebang correspondant au shell que vous avez réellement utilisé pour développer et déboguer votre script. Par exemple, 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 quelquebash
fonction que ce soit dont vous avez connaissance), vous êtes sûr de choisir le shell que vous préférez. Il existe de nombreuses différences subtiles entre les shells (echo
fonctions, boucles, etc.) qui ne peuvent ê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: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 le shebang par
#!/bin/sh
et le testez sur un système où se/bin/sh
trouve un lien symbolique vers/bin/bash
, vos utilisateurs qui n'en ont pasbash
auront des problèmes. Ils verront probablement un message d'erreur cryptique du type: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 shell différent dans le shebang. Une des raisons est que le shell que vous avez utilisé n'est pas répandu. Une autre solution consiste à obtenir des performances
sh
beaucoup plus rapides sur certains systèmes, ET votre script constituera un goulot d'étranglement en termes de performances. Dans ce cas, testez minutieusement votre script avec le shell cible, puis modifiez le shebang.la source
Vous ne devriez utiliser que jamais
#! /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 qui fonctionnent avec n'importe quelle implémentation du langage shell (y compris tous les programmes "utilitaires" associés au shell lui-même). De nos jours, vous pouvez probablement prendre POSIX.1-2001 (et non -2008) comme autorité pour tout ce que le shell et les utilitaires sont capables de faire, mais sachez que vous serez peut-être appelé un jour à porter votre script sur un système hérité (par exemple, Solaris ou AIX) dont la coque et les utilitaires ont été gelés vers 1992.
Quoi, sérieusement?!
Oui, vraiment.
Voici la chose: Shell est un langage de programmation terrible . La seule chose qui lui reste à faire, c’est
/bin/sh
le seul et unique interprète de script que chaque installation Unix possède.Voici l’autre chose: une certaine itération de l’interpréteur (
/usr/bin/perl
) Perl 5 principal est plus susceptible d’être disponible sur une installation Unix sélectionnée de manière aléatoire qu’elle ne l’(/(usr|opt)(/(local|sfw|pkg)?)?/bin/bash
est. D'autres bons langages de script (Python, Ruby, node.js, etc. - Je vais même inclure PHP et Tcl dans cette catégorie lors de la comparaison avec un shell) sont aussi à peu près aussi 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, de simples scripts shell, du genre qui ne fait que lancer quelques programmes dans l'ordre d'un job cron ou autre, rien de mal à les laisser en tant que scripts shell. Mais les scripts shell simples n'ont pas besoin de tableaux, de fonctions ou
[[
même. Et vous ne devriez écrire des scripts shell compliqués que 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 à chaque incarnation/bin/sh
correspondant au programme en cours de configuration. et cela signifie qu'ils ne peuvent utiliser aucune extension. Vous n'avez probablement pas à vous soucier des anciens Unix propriétaires, mais vous devriez probablement vous soucier des BSD Open Source actuels, dont certains ne sont pas installésbash
par défaut, et les environnements intégrés qui ne vous donnent qu'un shell minimal etbusybox
.En conclusion, au moment où vous vous trouvez à vouloir une 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éécris-le plutôt dans une meilleure langue.
la source
sh
. C’est cependant loin de dire qu’il ne faut jamais utiliser d’autres coquillages. Il y a des milliers (probablement beaucoup plus) de scripts écrits chaque jour et la grande majorité d'entre eux ne fonctionneront jamais que sur une seule machine. Vos conseils ont du sens pour le code de production, mais pas pour les tâches "sysdaminy" quotidiennes pour lesquelles la plupart des scripts sont écrits. Si je sais que mon script ne sera utilisé que par moi-même et sur une machine Linux, bash convient.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.
la source
Pour être encore plus bref, utilisez
sh
si la portabilité sur la plupart des systèmes est primordiale etbash
si vous souhaitez utiliser certaines de ses fonctionnalités spécifiques, telles que les tableaux, si la version de bash le prend en charge.la source
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 une modification, PATH peut changer:#! / usr / bin / env sh ou
#! / usr / bin / env bash
ou pour, 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 probable.
la source