Quand est-ce que #!/bin/bash
plus approprié que #!/bin/sh
dans un Shell Shell ?
Belle réponse. Vouliez-vous en faire un CW ?
Quand est-ce que #!/bin/bash
plus approprié que #!/bin/sh
dans un Shell Shell ?
En bref :
Il existe plusieurs shells qui implémentent un sur-ensemble de la spécification POSIX sh . Sur différents systèmes, /bin/sh
peut être un lien vers ash, bash, dash, ksh, zsh, &c. (Il sera cependant toujours compatible avec sh - jamais avec csh ou fish).
Tant que vous vous en tenez à sh
uniquement, vous pouvez (et devriez même) utiliser les fonctions #!/bin/sh
et le script devrait fonctionner correctement, quel que soit le script.
Si vous commencez à utiliser des fonctionnalités spécifiques à bash (par exemple, les tableaux), vous devez demander spécifiquement bash - parce que, même si /bin/sh
invoque déjà bash sur votre système, il pourrait ne pas l'être sur ceux de tous les autres et votre script ne s'y exécutera pas. (La même chose s'applique bien sûr à zsh et ksh.) Vous pouvez utiliser shellcheck pour identifier les bashismes.
Même si le script n'est destiné qu'à un usage personnel, vous pouvez remarquer que certains systèmes d'exploitation modifient /bin/sh
pendant les mises à jour - par exemple, sur Debian, c'était bash, mais il a été remplacé plus tard par un dash très minimal. scripts qui utilisaient des bashismes mais avaient des #!/bin/sh
s'est soudainement brisé.
Cependant :
Même #!/bin/bash
n'est pas très correct. Sur différents systèmes, bash pourrait vivre dans /usr/bin
o /usr/pkg/bin
o /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
fait.)
Juste une remarque si bash est exécuté à partir de /bin/sh
il essaiera alors d'imiter sh
(voir page de manuel ), mais il n'est pas certain que les fonctionnalités spécifiques à bash soient disponibles dans ce mode. env
l'outil est un outil posix il devrait se trouver dans la plupart des distributions, mais je n'en suis pas certain car certaines ne respectent pas posix.
Utilisez le shebang correspondant au Shell que vous avez effectivement utilisé pour développer et déboguer votre Shell. C'est-à-dire que si votre Shell de connexion est bash
et vous lancez votre script comme exécutable dans votre terminal, utilisez #!/bin/bash
. Ne présumez pas que, puisque vous n'avez pas utilisé de tableaux (ou autre) bash
que vous connaissez), vous pouvez choisir n'importe quel Shell que vous voulez. Il existe de nombreuses différences subtiles entre les shells ( echo
(fonctions, boucles, etc.) qui ne peuvent être découverts sans un test approprié.
Considérez ceci : si vous laissez #!/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 paquet approprié. D'un autre côté, 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 verront probablement un message d'erreur cryptique du genre :
Error in script.sh line 123: error parsing token xyz
Cela peut prendre des heures à réparer, et il n'y aura aucun indice sur le Shell qu'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 raison est lorsque le Shell que vous avez utilisé n'est pas répandu. Une autre est de gagner en performance avec sh
qui est nettement plus rapide sur certains systèmes, ET votre script sera un goulot d'étranglement en termes de performances. Dans ce cas, testez votre script minutieusement avec le script cible, puis changez le shebang.
Le chargement d'un interprète Shell supplémentaire à partir du système de fichiers peut annuler cet avantage, et tout ce qui concerne les nanosecondes (qui sont du même ordre de grandeur qu'un cycle machine réel) est le domaine des programmeurs en langage C et en langage d'assemblage.
Les nanosecondes ne font une différence dans les tâches cron que si vous en avez des milliards, et cron ne sera de toute façon pas en mesure d'en gérer autant.
Même si mckenzm a un peu exagéré, il est indéniable qu'il est préférable d'être plus performant ! Ne vous attardez pas sur la partie "nano". (Les nanosecondes ne comptent même pas en C, à moins qu'il ne s'agisse d'une boucle interne sur un système en temps réel ou autre).
#! /bin/sh
.Vous ne devez pas utiliser les extensions bash (ou zsh, ou fish, ou ...) dans un Shell Shell, jamais.
Vous ne devriez jamais écrire Shell Shell qui fonctionnent avec tout implémentation du langage Shell (y compris tous les programmes "utilitaires" qui vont de pair avec le Shell lui-même). De nos jours, vous pouvez probablement prendre POSIX.1-2001 ( no -2008) comme faisant autorité pour ce dont le Shell et les utilitaires sont capables, mais soyez conscient que vous pouvez un jour être appelé à porter votre Shell sur un système hérité (par exemple Solaris ou AIX) dont le Shell et les utilitaires ont été gelés vers 1992.
Oui, sérieusement.
Voilà le truc : Shell est un terrible le langage de programmation. La seule chose qu'il a en sa faveur est que /bin/sh
est le seul et unique interprète de script qui chaque L'installation Unix est garantie.
Autre chose : une itération de l'interpréteur Perl 5 de base ( /usr/bin/perl
) est plus susceptibles d'être disponibles 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'inclurai même PHP et Tcl dans cette catégorie lors de la comparaison avec Shell) sont également à 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, simple Shell Shell, le genre qui exécute juste quelques programmes dans une séquence à partir d'un travail cron ou autre, il n'y a rien de mal à les laisser comme Shell Shell. Mais les simples Shell Shell n'ont pas besoin de tableaux ou de fonctions ou de [[
même. Et vous devriez seulement écrire compliqué Shell Shell quand vous n'avez pas d'autre choix. Les Shell d'Autoconf, par exemple, sont toujours correctement Shell Shell. Mais ces Shell doivent s'exécuter sur chaque l'incarnation de /bin/sh
qui est pertinent pour le programme en cours de configuration. et cela signifie qu'ils ne peuvent pas utiliser d'extensions. Vous n'avez probablement pas à vous soucier des vieux Unix propriétaires de nos jours, mais vous avez probablement devrait se soucier des BSDs open-source actuels, dont certains n'installent pas bash
par défaut, et des environnements intégrés qui ne vous donnent qu'un Shell minimal et des busybox
.
En conclusion, au moment où vous vous trouvez voulant une fonctionnalité qui n'est pas disponible dans le langage portable Shell, c'est un signe que le Shell est devenu trop compliqué pour rester un Shell Shell. Réécrivez-le dans un meilleur langage à la place.
Désolé, mais c'est un peu idiot. Oui, si vous écrivez quelque chose qui sera i) distribué et ii) dans différents environnements, vous devriez vous en tenir à la version de base. sh
. Cela ne signifie pas pour autant qu'il faille affirmer qu'il faut nunca 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 s'exécutera jamais que sur une seule machine. Votre conseil a du sens pour le code de production, mais pas pour les tâches quotidiennes de "sysdaminy" pour lesquelles la plupart des scripts sont écrits. Si je sais que mon scripts ne sera jamais utilisé que par moi et sur une machine Linux, bash est parfait.
@terdon Le fait est que si vous avez la possibilité d'écrire un script bash, alors vous avez également la possibilité d'écrire un script perl (ou autre), et ceci est toujours le meilleur choix.
@terdon La réponse n'est sûrement pas idiote, votre commentaire au contraire est tout simplement naïf. Shell Shell est terriblement difficile à déboguer comparé à Perl et autres, pour lesquels on peut facilement utiliser des IDE complets avec débogage graphique et tout le reste. De plus, la plupart des Shell écrits chaque jour pour une petite chose à faire ont tendance à être modifiés et modifiés encore et encore, à grandir, à être copiés comme exemples à des collègues ou sur le net, etc. Il n'y a probablement aucune raison de prendre un tel risque.
SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.
56 votes
Lorsque vous utilisez
bash
plutôt qu'aux fonctions et à la syntaxe de lsh
les fonctions et la syntaxe.6 votes
Véase stackoverflow.com/questions/5725296/
3 votes
Si cela peut aider quelqu'un, j'ai remarqué que
vim
mettra en lumièrebash
-ismes si votre script possède la fonction#!/bin/sh
shebang. Je le change seulement enbash
si les choses deviennent suffisamment compliquées pour nécessiter des fonctions de base.0 votes
@SeldomNeedy Certaines des choses qu'il met en évidence par défaut fonctionnent bien dans n'importe quel Shell POSIX.
$(...)
est particulièrement odieuse. De plus, certains d'entre eux sont subtils [<(...)
ycmd >& file
n'ont pas de surbrillance d'erreur, par exemple, ils n'ont simplement pas de surbrillance spéciale pour ce qu'ils signifient, avec ou sansg:is_bash
]0 votes
@Random832 Il semble qu'il y ait eu de l'activité sur ce sujet récemment en l'outil de suivi des problèmes de vim .
0 votes
@Random832 Si les deux derniers idiomes que vous avez listés ne sont pas valides dans les shells Bourne (ce que vim suppose asinément sous le nom de
#!/bin/sh
sauf sig:is_bash
oug:is_posix
sont définies), serait-il judicieux de soumettre des questions à ce sujet ?0 votes
@SeldomNeedy De nos jours, on peut passer beaucoup de temps sans tomber sur un ancien Unix propriétaire (Solaris, HPUX, AIX, etc.), mais la plupart d'entre eux ont un système de gestion de la sécurité.
/bin/sh
(et les utilitaires default-$PATH) dont le comportement a été gelé circa 1992 afin qu'aucun des Shell Shell poussiéreux de leurs clients ne soit cassé par les changements de POSIX.1-1996 (ne parlons même pas de -2001 ou -2008 !), je ne recommande pas d'écrire nouveau Shell Shell pour faire face à cela - suffisamment bien pour y faire face si/quand cela se présente - mais en tant que personne qui utilisé pour Je suis confronté à cela tous les jours, et le comportement de Vim m'a séduit.