Utilisez #! / Bin / sh ou #! / Bin / bash pour la compatibilité Ubuntu-OSX et la facilité d'utilisation et POSIX

18

Je sais que je peux utiliser soit la première ligne de scripts pour invoquer le shell souhaité.

Serait #!/bin/shrecommandé si la compatibilité avec tous les systèmes Unix est une exigence absolue?

Dans mon cas, les seuls OS dont je me soucie sont Ubuntu (Debian) et OSX. Étant donné que, puis-je utiliser #!/bin/bashet être assuré que cela fonctionnerait sur les deux systèmes?
Cela faciliterait-il également l'utilisation de scripts avec une syntaxe plus moderne et plus claire pour les commandes? L'utilisation #!/bin/shconcerne- t-elle également l'utilisation de POSIX?

Michael Durrant
la source
1
Il vaut probablement la peine de noter que de nombreuses distributions ont commencé à fusionner /binet /usr/bin. En conséquence, il est probablement préférable d'utiliser la #!/usr/bin/env <shname>portabilité de nos jours.
HalosGhost

Réponses:

15

Pour commencer, si vous pouvez faire l'hypothèse que Bash est préinstallé (ce qui, à ma connaissance, est le cas sur tous les systèmes que vous répertoriez), utilisez le hashbang suivant pour être compatible:

#!/usr/bin/env bash

cela appelle tout ce qui bashse passe à configurer, que ce soit dans /binou /usr/local/bin.

Alors que sur la plupart des systèmes à travers une large gamme (y compris AIX, Solaris, plusieurs versions BSD), bashse sont retrouvés à différents endroits, se sont envtoujours retrouvés /usr/bin/env. L'astuce, cependant, n'est pas la mienne mais celle de l'auteur du Bash Cookbook.

Quoi qu'il en soit, oui, Bash vous permettrait d'utiliser des fonctionnalités "modernes" qui vous simplifient la vie.

Par exemple les doubles crochets:

[[ -f "/etc/debian_version" ]] && echo "This is a Debian flavor"

alors que dans les dialectes shell traditionnels, il faudrait recourir à:

test -f "/etc/debian_version" && echo "This is a Debian flavor"

mais le meilleur des crochets doubles est qu'ils autorisent les expressions régulières pour la correspondance. Le wiki Bash Hackers vous donnera de nombreuses astuces dans cette direction.

Vous pouvez également utiliser des expressions assez pratiques comme $((2**10))ou d'autres expressions arithmétiques en ligne avec la $((expression))syntaxe.

L'utilisation de backticks pour les sous-coquilles est correcte, bien qu'un peu dépassée. Mais les capacités d'imbrication des $(command ...)invocations sont bien plus pratiques car vous n'aurez pas à échapper à beaucoup de choses à différents niveaux de sous-shell.

Ce ne sont que quelques choses que Bash vous donne sur la shsyntaxe POSIX commune traditionnelle .

Mais si vous voulez plus de puissance sur le shell (pas seulement dans les scripts), jetez également un œil à zsh.

0xC0000022L
la source
Bash est un outil très utile mais veillez à ne pas l'utiliser pour démarrer des services qui pourraient être vulnérables à un bogue de script Bash, par exemple access.redhat.com/security/cve/CVE-2014-6271 . Restez fidèle à shces tâches.
Rick-777
1
Rick-777 que la vulnérabilité était largement exagérée et à mon avis, votre commentaire est FUD. Si un service système s'exécute sous bash, il n'est en aucune façon vulnérable à ce bogue. Il n'est vulnérable à ce bogue que s'il accélère un processus bash tout en permettant aux utilisateurs distants d'accéder directement à une ou plusieurs variables d'environnement, comme dans FastCGI, et même alors uniquement sur les versions non corrigées de bash. Sur les systèmes shliés à bash, la vulnérabilité ne sera pas atténuée par l'utilisation sh.
Score_Under
11

Dans Debian et Ubuntu, /bin/shis dash, qui est un shell compatible POSIX. Si vous spécifiez #!/bin/sh, vous devez vous limiter aux instructions POSIX dans votre script. (L'avantage étant qu'il dashdémarre plus rapidement que bash, de sorte que votre script peut faire son travail en moins de temps.)

Sur de nombreux (la plupart?) Autres systèmes Linux, /bin/shc'est la bashraison pour laquelle de nombreux scripts sont écrits avec #!/bin/shleur ligne shebang même s'ils utilisent des bashextensions.

Si vous souhaitez utiliser des bashextensions, l'approche la plus sûre sur tous les systèmes consiste à spécifier #!/bin/bash; de cette façon, vous déclarez explicitement votre dépendance bash. Vous devez le faire sur Debian et Ubuntu. En prime, une fois démarré, il /bin/sh bashdésactive certaines extensions (voir la description du bashmode POSIX pour plus de détails); il #!/bin/bashest donc nécessaire de spécifier pour bénéficier pleinement de bash.

Sur OS X /bin/bashest également disponible, et l' /bin/shest bash. La spécification #!/bin/bashfonctionnera également bien là-bas.

Stephen Kitt
la source
5

Oui, OSX et Linux seront fournis avec /bin/bash. Vous devriez être parfaitement en sécurité. Cependant, ce n'est pas POSIX. Le shell POSIX est /bin/shsur la plupart (tous?) Des systèmes et c'est l'approche la plus portable et la seule façon d'être compatible POSIX.

Notez que tandis que sur de nombreux systèmes /bin/shpointe vers bash, sur d'autres, il peut pointer vers différents shells. C'est un lien symbolique vers dashDebian et Ubuntu par exemple. De plus, même s'il /bin/shs'agit d'un lien vers bash, le comportement du shell change quand il est appelé comme sh(from man bash, accent mine):

Si bash est appelé avec le nom sh, il essaie d'imiter le comportement de démarrage des versions historiques de sh aussi fidèlement que possible, tout en se conformant également à la norme POSIX. Lorsqu'il est invoqué en tant que shell de connexion interactif ou shell non interactif avec l'option --login, il tente d'abord de lire et d'exécuter des commandes à partir de / etc / profile et ~ / .profile, dans cet ordre. L'option --noprofile peut être utilisée pour inhiber ce comportement. Lorsqu'elle est invoquée en tant que shell interactif avec le nom sh, bash recherche la variable ENV, développe sa valeur si elle est
défini et utilise la valeur développée comme nom d'un fichier à lire et à exécuter. Puisqu'un shell appelé comme sh n'essaye pas de lire et d'exécuter des commandes à partir d'autres fichiers de démarrage, l'option --rcfile n'a aucun effet. Un shell non interactif appelé avec le nom sh n'essaie pas de lire d'autres fichiers de démarrage. Lorsqu'il est appelé en tant que sh, bash entre en mode posix après la lecture des fichiers de démarrage.

terdon
la source
2

Si la compatibilité avec "tous les systèmes Unix" est une exigence absolue - et si ce n'est pas le cas, pourquoi écrivez-vous un script shell? - alors, oui, vous devriez utiliser #! /bin/sh, car Bash n'est pas garanti d'être installé n'importe où , et encore moins à l'intérieur /bin.

C'est en fait bien, bien pire que ça. Si vous avez besoin de compatibilité avec tous les systèmes Unix, cela inclut des choses comme Solaris et AIX qui ont gelé leurs environnements shell vers 1995. Ce qui signifie que vous devez utiliser des choses comme l'ancienne sort +Nsyntaxe - que les nouveaux systèmes ont abandonné! Et cela signifie également pas de fonctions shell, pas de tableaux, non [[ ... ]], non ${foo#glob}, non $(( ... ))pour l'arithmétique, éventuellement pas de $( ... )substitution de commande de style, de petites limites supérieures non documentées sur la taille des entrées, ...

Vous pouvez probablement vous en sortir sans se soucier de cette compatibilité beaucoup, mais si elle est encore un problème en premier lieu, je recommande fortement que vous considérez une langue qui est moins terrible que la coquille. L'interpréteur Perl de base est plus susceptible d'être disponible que Bash.

zwol
la source
Merci. Comme indiqué à l'origine "Dans mon cas, les seuls OS dont je me soucie sont Ubuntu (Debian) et OSX.". Ce sont les 2 seuls systèmes que j'ai utilisés (et je les utilise beaucoup) au cours des 5 dernières années, c'est pourquoi 'j'écris un script shell qui ne fonctionnerait que sur eux. Je n'ai pas du tout besoin d'un script universel et des limites qu'il présenterait.
Michael Durrant
@MichaelDurrant Dans ce cas, vous n'avez pas besoin, et ne devez pas, écrire un script shell. Au lieu de cela, vous devriez utiliser l'un des nombreux langages de script améliorés qui sont une option lorsque vous n'avez pas besoin d'une portabilité totale.
zwol