Question Quand faut-il utiliser #! / Bin / bash et quand #! / Bin / sh?


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


97
2017-10-10 07:02


origine


Lorsque vous utilisez bash fonctions et syntaxe plutôt que sh fonctions et syntaxe. - Mokubai♦
Voir stackoverflow.com/questions/5725296/... - SPRBRN
Si cela aide quelqu'un, j'ai remarqué que vim mettra en évidence bash-isms si votre script a le #!/bin/sh case. Je le change seulement pour bash si les choses deviennent assez poilues pour commencer à avoir besoin de fonctionnalités bash. - SeldomNeedy
@SeldomNeedy Certaines des choses mises en évidence par défaut fonctionnent bien dans tout shell POSIX. $(...) est particulièrement odieux. En outre, certains d'entre eux sont subtils [<(...) et cmd >& file ne pas avoir d'erreur de mise en évidence, par exemple, ils n'ont tout simplement pas de mise en évidence spéciale pour ce qu'ils veulent dire, avec ou sans g:is_bash] - Random832
@ Random832 On dirait qu'il y a eu de l'activité sur ce sujet récemment Vim's issue-tracker. - SeldomNeedy


Réponses:


En bref:

  • Il existe plusieurs coques qui implémentent un sur-ensemble de la spécification POSIX sh. Sur différents systèmes, /bin/sh pourrait être un lien vers ash, bash, dash, ksh, zsh, & c. (Il sera toujours compatible avec sh, mais jamais csh ou fish.)

  • Tant que vous vous en tenez à sh fonctionnalités uniquement, vous pouvez (et probablement même devrait) utiliser #!/bin/sh et le script devrait fonctionner correctement, quel que soit le shell.

  • Si vous commencez à utiliser des fonctionnalités spécifiques à bash (par exemple, des tableaux), vous devez demander spécifiquement bash - car même si /bin/sh invoque déjà bash on votre système, il pourrait ne pas sur tout le monde système, et votre script ne fonctionnera pas là. (La même chose s’applique bien sûr à zsh et ksh.) Vous pouvez utiliser shellcheck identifier les bashismes.

  • Même si le script est à usage personnel uniquement, vous remarquerez peut-être que certains systèmes d’exploitation changent /bin/sh pendant les mises à niveau - par ex. sur Debian, c'était bash, mais plus tard, il a été remplacé par un tiret minimal. Scripts qui utilisaient des basismes mais avaient #!/bin/sh brusquement brisé.

Toutefois:

  • Même #!/bin/bash n'est pas très correct Sur différents systèmes, bash pourrait 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 le env l'outil lui-même n'est pas strictement garanti non plus, /usr/bin/env fonctionne toujours sur plus de systèmes que /bin/bash Est-ce que.)


142
2017-10-10 14:03



Bonne réponse. Vouliez-vous le rendre CW? - Mokubai♦
Juste une remarque si bash est lancé à partir de /bin/sh alors il va essayer d'imiter sh caractéristiques (voir page de man), certaines fonctionnalités spécifiques à bash ne sont pas disponibles dans ce mode. env l'outil est un outil de pose il faut le trouver dans la plupart des distributions, mais je ne suis pas certain car certains ne respectent peut-être pas le posix. - Brice
Non, en fait POSIX stipule spécifiquement il ne peut pas être supposé être en /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 PATH renvoyé par getconf PATH, en veillant à ce que le chemin renvoyé soit absolu chemin d'accès et non un shell intégré". Regarde aussi cette question et spécifiquement cette réponse. - terdon
Hmm, eh bien, cela signifie que POSIX ne définit pas réellement une manière portable d'avoir #! les scripts fonctionnent? - grawity
POSIX sh est ne pas Bourne: c'est plus un dérivé du début ksh qu'un descendant direct de Bourne. Les distinguer est facile: echo foo ^ cat émet foo ^ cat dans POSIX sh, et émet seulement foo à Bourne (comme ^ est un personnage de pipe ici). - Charles Duffy


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 vous exécutez votre script comme exécutable dans votre terminal, utilisez #!/bin/bash. Ne vous contentez pas de supposer que puisque vous n’avez pas utilisé de tableaux bash fonction que vous connaissez), vous êtes sûr de choisir quel que soit le shell que vous aimez. Il y a beaucoup de différences subtiles entre les coquilles (echo, fonctions, boucles, vous le nommez) qui ne peuvent être découverts sans tests appropriés.

Considérez ceci: si vous partez #!/bin/bash et 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é. Par contre, si vous remplacez le shebang par #!/bin/sh et le tester sur un système où /bin/sh est un lien symbolique vers /bin/bash, vos utilisateurs qui n’ont pas bash sera en difficulté. Ils vont probablement voir un message d'erreur cryptique comme:

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

Cela peut prendre des heures à corriger, 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. L'une des raisons est que le shell que vous avez utilisé n'est pas répandu. Un autre est de gagner en performance avec sh ce qui est beaucoup plus rapide sur certains systèmes, ET votre script sera un goulot d'étranglement. Dans ce cas, testez votre script avec le shell cible, puis changez le shebang.


17
2017-10-14 13:55



@Hastur Je n'ai pas votre commentaire. Le shebang définira certainement quel shell sera utilisé pour exécuter le script, pensez-vous que ma réponse implique le contraire? - Dmitry Grigoryev
Oublie. J'ai mal compris la partie "Pourquoi voudriez-vous utiliser"... - Hastur


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

Vous ne devez jamais utiliser les extensions bash (ou zsh, ou fish ou ...) dans un script shell.

Vous ne devriez jamais écrire que des scripts shell qui fonctionnent avec tout Implémentation du langage shell (incluant tous les programmes "utilitaires" qui accompagnent le shell lui-même). Ces jours vous pouvez Probablement prendre POSIX.1-2001 (ne pas -2008) comme faisant autorité pour ce que le shell et les utilitaires sont capables de faire, mais sachez que vous pourriez un jour être amené à porter votre script sur un système hérité (Solaris ou AIX, par exemple) dont le shell et les utilitaires ont été gelés vers 1992.

Quoi, sérieusement?!

Oui, vraiment.

Voici la chose: Shell est un terrible langage de programmation. La seule chose qu'il a fait c'est que /bin/sh est le seul et unique interpréteur de script chaque L'installation d'Unix est garantie.

Voici l'autre chose: une itération de l'interpréteur principal de Perl 5 (/usr/bin/perl) est plus susceptible d'être disponible sur une installation Unix sélectionnée au hasard que (/(usr|opt)(/(local|sfw|pkg)?)?/bin/bash est. D'autres bons langages de script (Python, Ruby, node.js, etc. - j'inclus même PHP et Tcl dans cette catégorie en comparaison avec le shell) sont également disponibles à peu près comme bash et 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.

À présent, simple Les scripts shell, le type qui exécute juste quelques programmes dans une séquence à partir d'un job cron ou quelque chose, il n'y a rien de mal à les laisser en tant que scripts shell. Mais les scripts shell simples n'ont pas besoin de tableaux ou de fonctions ou [[ même. Et vous devriez seulement écrire compliqué scripts shell lorsque vous n’avez pas d’autre choix. Les scripts Autoconf, par exemple, sont toujours des scripts shell. Mais ces scripts doivent fonctionner sur chaque incarnation de /bin/sh cela est pertinent pour le programme en cours de configuration. et cela signifie qu'ils ne peuvent utiliser aucune extension. Vous n'avez probablement pas à vous soucier des vieux Unix propriétaires, mais vous avez probablement devrait se soucient des BSD open-source actuels, dont certains ne s'installent pas bash par défaut, et les environnements intégrés qui ne vous donnent qu'un shell minimal et busybox.

En conclusion, le moment où vous vous trouvez vouloir une fonctionnalité qui n'est pas disponible dans le langage shell portable, c'est un signe que le script est devenu trop compliqué pour rester un script shell. Réécrivez-le dans une meilleure langue.


5
2017-10-11 06:30



Désolé mais c'est un peu idiot. Oui, si vous écrivez quelque chose qui sera distribué et ii) à différents environnements, vous devriez vous en tenir à la base sh. Cela, cependant, est loin de dire que vous devriez jamais utiliser d'autres coquilles. Il y a des milliers (probablement beaucoup plus) de scripts écrits chaque jour et la grande majorité d'entre eux ne fonctionneront que sur une seule machine. Votre avis a du sens sur le code de production, mais pas sur les tâches quotidiennes "sysdaminy" pour lesquelles la plupart des scripts sont écrits. Si je sais que mon script ne sera utilisé que par moi et sur une machine Linux, bash va bien. - terdon
@terdon Le fait est que si vous avez la possibilité d'écrire un script bash, vous avez également la possibilité d'écrire un script perl (ou autre), et ceci est toujours le meilleur choix. - zwol
@terdon La réponse n'est sûrement pas idiote, votre commentaire est plutôt naïf. Les scripts shell sont terribles à déboguer par rapport à Perl et autres, pour lesquels on peut facilement utiliser des IDE complets avec débogage graphique et tout. De plus, la plupart des scripts écrits chaque jour pour des petites choses à faire ont tendance à être changés et changés à nouveau, grandissent, sont copiés comme exemples pour des collègues ou sur le réseau, etc. Il n'y a très probablement aucune raison de prendre un tel risque. - Thorsten Schöning
@ ThorstenSchöning j'ai dit un peu idiot. Si c'était Unix et Linux ou même Débordement de pile Je pourrais même être d'accord. Si nous parlons des meilleures pratiques générales, ou des programmeurs professionnels, il est bien sûr préférable de s’en tenir aux bases de POSIX. Cependant, c'est Super utilisateur, un site destiné aux utilisateurs finaux et demandant aux utilisateurs de ne jamais utiliser bash ou zsh lors de l'écriture de scripts shell est, à mon avis, extrême. - terdon
@terdon C'est en fait plus À mon avis, il est important de décourager les utilisateurs finaux d’écrire des scripts complexes. Les professionnels ont en moyenne un niveau de compétence plus élevé (ils sont donc plus à même de faire face aux écueils des scripts shell complexes), doivent savoir avec précision les environnements sur lesquels ils doivent être portables et sont payés pour ne pas abandonner dans la frustration. - zwol


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


3
2017-10-11 20:36



Le chargement d'un interpréteur de shell supplémentaire à partir du système de fichiers peut annuler un tel avantage, et tout ce qui concerne les nanosecondes (qui sont dans le même ordre de grandeur qu'un cycle de machine réel) est le domaine des programmeurs en langage C et assembleur. - rackandboneman
Les nanosecondes ne font qu'une différence dans les tâches cron si vous en avez des milliards, et cron ne pourra pas en gérer autant. - Dmitry Grigoryev
Même si mckenzm a exagéré un peu, il est indéniable que le fait d'avoir plus de performance est meilleur! Ne pas raccrocher sur la partie "nano". (Les nanosecondes ne comptent même pas dans C à moins que ce ne soit une boucle interne sur un système en temps réel ou autre!) - jpaugh
@jpaugh Sauf si vous travaillez avec un système (hérité) qui suppose que certaines opérations dureront au moins une période donnée. Ça arrive! - JAB


Pour être encore plus bref, utilisez sh si la portabilité sur la plupart des systèmes est la plus importante 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.


2
2017-11-24 18:41





  • sh (pour la plupart des cas), bash si nécessaire (ou ksh, ou autre)

Le chemin le plus sûr si codé en dur, serait / usr / bin /shellOfChoice mais une nouvelle convention que j'essaye toujours d'utiliser maintenant - en tant que «emplacements par défaut» via un changement que PATH peut changer est:

#! / usr / bin / env sh ou
 #! / usr / bin / env bash
ou pour, par exemple, des scripts perl
 #! / usr / bin / env perl -w

Bien sûr, lorsque vous avez une raison pour qu'un script ne prenne JAMAIS automatiquement un nouveau PATH, continuez à le faire coder en dur - et ensuite / usr / bin / quelquechose devrait être le chemin le plus probable à utiliser.


1