Quel est le shebang Bash préféré?

1132

Existe-t-il un Bashshebang objectivement meilleur que les autres pour la plupart des utilisations?

  • #!/usr/bin/env bash
  • #!/bin/bash
  • #!/bin/sh
  • #!/bin/sh -
  • etc

Je me souviens vaguement d'entendre il y a longtemps que l'ajout d'un tiret à la fin empêche quelqu'un de passer une commande à votre script, mais ne trouve aucun détail à ce sujet.

Kurtosis
la source
4
Et c'est /usr/local/bin/bashsur OpenBSD.
Jww

Réponses:

1536

Vous devez utiliser #!/usr/bin/env bashpour la portabilité : différents * nixes placés bashà différents endroits, et l'utilisation /usr/bin/envest une solution de contournement pour exécuter le premier bashtrouvé sur le PATH. Et ce shn'est pas le casbash .

l0b0
la source
9
Merci. On dirait aussi que l'ajout - à la fin de $! / Usr / bin / env bash - ne fera rien car un seul argument est autorisé par * nix dans le shebang, et qui est utilisé par 'bash'. Cela n'est apparemment utile que pour empêcher la transmission d'arguments malveillants au script sur la ligne de commande si le shebang du script est l'un des autres sans arguments ( /bin/sh, etc.).
Kurtosis
13
@Ray bashne vit pas /binsur tous les systèmes.
ptierno
12
Même chose pour moi, je viens de l'ajouter à un alias:, alias shebang='echo "#!/usr/bin/env bash"'maintenant je dois juste ouvrir le terminal et taper shebang au lieu d'aller ici.
Oylex
19
Cette réponse est trompeuse. POSIX ne dit pas que envc'est à /usr/bin/env. Cela pourrait être à /bin/envou n'importe où en fait, tant qu'il est sur le chemin. Cela pourrait être à /dummy/envsi /dummyest dedans PATH. Shebang lui-même n'est pas défini sous POSIX, donc je pourrais faire #!stop toasterdémarrer la machine à café USB et être compatible POSIX. Ce #!/usr/bin/env bashn'est donc pas mieux que #!/bin/bashça, ça pourrait être moins portable selon.
darkfeline
19
@darkfeline La portabilité n'est pas absolue - il est mathématiquement impossible de créer un script qui fera la même chose sur chaque plate-forme. De 2012 à 2018 /usr/bin/envexiste sur plus de machines que sur /bin/bashxor /usr/bin/bash, donc un script qui commence par cette ligne fera la chose attendue sur autant de machines que possible.
l0b0
80

/bin/shest généralement un lien vers le shell par défaut du système, ce qui est souvent bashle cas, par exemple, les systèmes Debian sont plus légers dash. Quoi qu'il en soit, le shell Bourne d'origine est sh, donc si votre script utilise bashdes fonctionnalités spécifiques (2e génération, "Bourne Again sh") ( [[ ]]tests, tableaux, diverses choses sucrées, etc.), alors vous devriez être plus spécifique et utiliser la dernière . De cette façon, sur les systèmes où bash n'est pas installé, votre script ne s'exécutera pas. Je comprends qu'il peut y avoir une trilogie passionnante de films sur cette évolution ... mais cela pourrait être du ouï-dire.

Notez également que lorsqu'il est évoqué comme sh, bashil se comporte dans une certaine mesure comme la norme POSIXsh (voir également les documents GNU à ce sujet).

délicatTissuFièvre
la source
2
Le domaine public Korn Shell (pdksh) est par défaut sur OpenBSD.
Jww
La plupart des systèmes ne seront liés /bin/shà aucun endroit /usrcar cela rendrait plutôt difficile l'exécution des scripts d'initialisation avant le /usrmontage.
aij
@aij Je ne sais pas pourquoi j'y mets "beaucoup ou la plupart" - je suis un utilisateur de fedora, où /binet /sbinpendant des années viennent d'être des liens symboliques par défaut, vers /usr/binet /usr/sbin, donc dans ce contexte /bin/shest un lien vers bashet le réel répertoire est /usr/bin. Mais je vais corriger ce qui précède.
delicateLatticeworkFever
44

Je recommande d'utiliser:

#!/bin/bash

Ce n'est pas 100% portable (certains systèmes placent bashdans un endroit autre que /bin), mais le fait que beaucoup de scripts existants utilisent des #!/bin/bashpressions différents systèmes d'exploitation pour faire /bin/bashau moins un lien symbolique vers l'emplacement principal.

L'alternative de:

#!/usr/bin/env bash

a été suggéré - mais il n'y a aucune garantie que la envcommande se trouve /usr/bin(et j'ai utilisé des systèmes là où elle ne l'est pas). De plus, ce formulaire utilisera la première instance de bashdans les utilisateurs actuels $PATH, ce qui pourrait ne pas être une version appropriée du shell bash.

(Mais /usr/bin/envdevrait fonctionner sur n'importe quel système raisonnablement moderne, soit parce qu'il envest installé, soit parce /usr/binque le système fait quelque chose pour le faire fonctionner. Le système auquel j'ai fait référence ci-dessus était SunOS 4, que je n'ai probablement pas utilisé depuis environ 25 ans.)

Si vous avez besoin d'un script pour s'exécuter sur un système qui n'en a pas /bin/bash, vous pouvez modifier le script pour pointer vers l'emplacement correct (ce qui est certes gênant).

J'ai discuté des compromis plus en profondeur dans ma réponse à cette question .

Une mise à jour quelque peu obscure: un système que j'utilise, Termux , une couche de type Linux de bureau qui fonctionne sous Android, n'a pas /bin/bash( bashest /data/data/com.termux/files/usr/bin/bash) - mais il a une gestion spéciale à prendre en charge #!/bin/bash.

Keith Thompson
la source
3
2 ans plus tard et c'est toujours le meilleur conseil ici. Si la solution simple ne fonctionne pas, vous devez remettre en question vos décisions antérieures. La réponse acceptée et la plus votée n'est pas fausse, elle n'est tout simplement pas correcte :)
Ingénieur logiciel
27

L'utilisation d'une ligne shebang pour appeler l'interpréteur approprié n'est pas uniquement pour BASH. Vous pouvez utiliser le shebang pour n'importe quel langage interprété sur votre système tel que Perl, Python, PHP (CLI) et bien d'autres. Au fait, le shebang

#!/bin/sh -

(il peut également y avoir deux tirets, c'est-à-dire --).

L'utilisation de la envcommande rend votre script portable et vous permet de configurer des environnements personnalisés pour votre script, donc les scripts portables doivent utiliser

#!/usr/bin/env bash

Ou pour quelque langue que ce soit comme Perl

#!/usr/bin/env perl

N'oubliez pas de consulter les manpages pour bash:

man bash

et env:

man env

Remarque: Sur Debian et les systèmes basés sur Debian, comme Ubuntu, shest lié à dashpas bash. Comme tous les scripts système l'utilisent sh. Cela permet à bash de croître et au système de rester stable, selon Debian.

En outre, pour conserver l'invocation * nix comme je n'utilise jamais d'extensions de fichier sur les scripts invoqués par shebang, car vous ne pouvez pas omettre l'extension lors de l'invocation sur les exécutables comme vous pouvez le faire sous Windows. La commande file peut l'identifier comme un script.

Jamie R Robillard Sr.
la source
4

Cela dépend vraiment de la façon dont vous écrivez vos scripts bash. Si votre /bin/shest lié à bash, lorsque bash est appelé as sh, certaines fonctionnalités ne sont pas disponibles .

Si vous voulez des fonctionnalités spécifiques à bash, non POSIX, utilisez #!/bin/bash

glenn jackman
la source
3
Bash n'est pas installé sur OpenBSD. Si vous l'installez via pkg_add, il est situé dans /usr/local/bin, qui peut ne pas être sur le chemin.
jww
que diriez-vous d'une POSIXfonctionnalité?
Nikolan Asad