En général, les scripts shell contiennent le commentaire suivant à la première ligne du fichier script: #!/bin/sh
. Selon les recherches que j'ai faites, cela s'appelle "hash bang" et c'est un commentaire conventionnel. Ce commentaire informe Unix que ce fichier est exécuté par le Bourne Shell sous le répertoire /bin
.
Ma question commence par ce point. Jusqu'à présent, je n'ai pas vu ce commentaire comme #!/bin/bash
. C'est toujours #!/bin/sh
. Cependant, les distributions Ubuntu n'ont pas le programme Bourne Shell. Ils ont le Bourne Again Shell (bash).
À ce stade, est-il correct de placer le commentaire #!/bin/sh
dans des scripts shell écrits dans des distributions Ubuntu?
shebang
Réponses:
#!/bin/sh
devrait fonctionner sur toutes les distributions Unix et Unix. Il est généralement considéré comme le hashbang le plus portable tant que votre script est conforme à POSIX. Le/bin/sh
shell est censé être un shell qui implémente la norme shell POSIX, quel que soit le shell réel qui se fait passer pour le/bin/sh
shell.#!/bin/sh
est normalement juste un lien maintenant car le shell Bourne n'est plus maintenu. Sur de nombreux systèmes Unix/bin/sh
sera un lien vers/bin/ksh
ou/bin/ash
, sur de nombreux systèmes Linux basés sur RHEL, ce sera un lien vers/bin/bash
, cependant sur Ubuntu et sur de nombreux systèmes basés sur Debian, c'est un lien vers/bin/dash
. Tous les shells, lorsqu'ils sont appelés en tant quesh
, entreront en mode de compatibilité POSIX.Le hashbang est un espace réservé important car il permet une portabilité beaucoup plus grande que les autres méthodes, tant que votre script est strictement conforme à POSIX (répété pour souligner l'importance).
Remarque: Quand
bash
est invoqué en mode POSIX, il autorisera toujours certaines choses non POSIX comme les[[
tableaux et bien plus encore. Ces choses peuvent échouer sur un non-bash
système.la source
/bin/ash
.#! /
lieu de simplement#!
.Vous l'avez en arrière.
/bin/sh
n'est presque jamais une coquille Bourne de nos jours, et c'est quand c'est¹ que vous avez un problème lorsque vous utilisez une#! /bin/sh
she-bang.Le obus Bourne était un obus écrit à la fin des années 70 et a remplacé le précédent obus Thompson (également appelé
sh
). Au début des années 80, David Korn a écrit quelques extensions pour le shell Bourne, corrigé quelques bugs et conçu des maladresses (et en a introduit) et l'a appelé le shell Korn.Au début des années 90, POSIX a spécifié le
sh
langage basé sur un sous-ensemble du shell Korn et la plupart des systèmes¹ ont désormais changé/bin/sh
pour le shell Korn ou un shell conforme à cette spécification. Dans le cas des BSD, ils ont progressivement changé leur/bin/sh
, initialement (après qu'ils ne pouvaient plus utiliser le shell Bourne pour des raisons de licence) le shell Almquist, un clone du shell Bourne avec quelques extensions ksh donc il est devenu conforme POSIX.Aujourd'hui, tous les systèmes POSIX ont un shell appelé
sh
(le plus souvent, mais pas nécessairement dans/bin
, POSIX ne spécifie pas le chemin des utilitaires qu'il spécifie) qui est principalement conforme à POSIX. Il est généralement basé sur ksh88, ksh93, pdksh, bash, ash ou zsh², mais pas sur le shell Bourne car le shell Bourne n'a jamais été conforme POSIX³. Quelques - unes de ces coquilles (bash
,zsh
,yash
et certainspdksh
dérivés permettent un mode compatible POSIX lorsqu'il est invoqué commesh
et sont moins conformes par ailleurs).bash
(la réponse GNU au shell Korn) est en fait le seul shell open source (et on pourrait dire seulement actuellement maintenu car les autres sont généralement basés sur ksh88 qui n'a obtenu aucune nouvelle fonctionnalité depuis les années 90) qui a été certifié comme être conforme à POSIXsh
(dans le cadre de la certification macOS).Lorsque vous écrivez un script avec un
#! /bin/sh -
she-bang, vous devez utiliser unesh
syntaxe standard (et également utiliser la syntaxe standard pour les utilitaires utilisés dans ce script si vous voulez être portable, ce n'est pas seulement le shell qui est impliqué lors de l'interprétation d'un shell script), peu importe l'implémentation de cetsh
interpréteur de syntaxe standard utilisée (ksh
,bash
...).Peu importe que ces shells aient des extensions par rapport à la norme tant que vous ne les utilisez pas. C'est comme pour écrire du code C, tant que vous écrivez du code C standard et que vous n'utilisez pas d'extensions d'un compilateur (comme
gcc
) ou de l'autre, votre code devrait compiler OK quelle que soit l'implémentation du compilateur à condition que le compilateur soit conforme.Ici, avec votre
#! /bin/sh
elle-bang, votre principal problème serait les systèmes où/bin/sh
est le shell Bourne que par exemple ne prend pas en charge des fonctionnalités standard comme$((1+1))
,$(cmd)
,${var#pattern}
... Dans ce cas , vous devrez peut - être contournements comme:Par ailleurs, Ubuntu
/bin/sh
n'est pasbash
par défaut. C'est dedash
nos jours, un shell basé sur NetBSDsh
, lui-même basé sur le shell Almquist qui est principalement compatible POSIX, sauf qu'il ne prend pas en charge les caractères multi-octets. Sur Ubuntu et d'autres systèmes basés sur Debian, vous pouvez choisir entrebash
etdash
pour/bin/sh
avecdpkg-reconfigure dash
) 4 .sh
les scripts fournis avec Debian devraient fonctionner de la même manière dans les deux shells car ils sont écrits dans le standard de politique Debian (un surensemble du standard POSIX). Vous constaterez probablement qu'ils fonctionnent aussi bien danszsh
l'sh
émulation debosh
( ou probablement pasksh93
etyash
qui n'ont pas de fonctionlocal
intégrée (requis par la politique Debian mais pas POSIX)).Tous les systèmes concernés par unix.stackexchange.com ont un POSIX
sh
quelque part. La plupart d'entre eux ont un/bin/sh
(vous pouvez en trouver de très rares qui n'ont pas de/bin
répertoire mais vous ne vous en souciez probablement pas), et c'est généralement unsh
interpréteur POSIX (et dans de rares cas un shell Bourne (non standard) à la place ).Mais
sh
c'est le seul exécutable interpréteur de shell que vous pouvez être sûr de trouver sur un système. Pour les autres shells, vous pouvez être sûr que macOS, Cygwin et la plupart des distributions GNU / Linux aurontbash
. Les systèmes d'exploitation dérivés de SYSV (Solaris, AIX ...) auront généralement ksh88, éventuellement ksh93. OpenBSD, MirOS aura un dérivé pdksh. macOS aurazsh
. Mais hors de cela, il n'y aura aucune garantie. Aucune garantie que ce soitbash
ou l'un de ces autres shells sera installé dans/bin
ou ailleurs (il se trouve généralement dans/usr/local/bin
les BSD lors de l'installation par exemple). Et bien sûr aucune garantie de la version du shell qui sera installée.Notez que ce
#! /path/to/executable
n'est pas une convention , c'est une fonctionnalité de tous les noyaux de type Unix ( introduite au début des années 80 par Dennis Ritchie ) qui permet d'exécuter des fichiers arbitraires en spécifiant le chemin de l'interpréteur dans une première ligne commençant par#!
. Il peut s'agir de n'importe quel exécutable.Lorsque vous exécutez un fichier dont la première ligne commence par
#! /some/file some-optional-arg
, le noyau finit par s'exécuter/some/file
avecsome-optional-arg
, le chemin du script et les arguments d'origine comme arguments. Vous pouvez faire cette première ligne#! /bin/echo test
pour voir ce qui se passe:Lorsque vous utilisez à la
/bin/sh -
place de/bin/echo test
, le noyau s'exécute/bin/sh - ./myscript foo
,sh
interprète le code de contenu stocké dansmyscript
et ignore cette première ligne car il s'agit d'un commentaire (commence par#
).¹ Probablement le seul système aujourd'hui où l'un de nous rencontrera un
/bin/sh
qui est basé sur le shell Bourne est Solaris 10. Solaris est l'un des rares Unices qui a décidé de garder un shell Bourne là pour la compatibilité descendante (lesh
langage POSIX n'est pas complètement rétrocompatible avec le shell Bourne) et (au moins pour les déploiements de bureau et de serveur complet) ont le POSIXsh
ailleurs (dans/usr/xpg4/bin/sh
, basé sur ksh88), mais cela a changé dans Solaris 11 où/bin/sh
est maintenant ksh93. Les autres sont pour la plupart disparus.² Le
/bin/sh
MacOS / X était autrefoiszsh
, mais plus tard changé enbash
. Ce n'est paszsh
l'objectif principal d'être utilisé comme unesh
implémentation POSIX . Sonsh
mode est avant tout de pouvoir embarquer ou appeler (source
) dush
code POSIX dans deszsh
scripts³ Récemment, @schily a étendu le shell OpenSolaris (basé sur le shell SVR4, basé sur le shell Bourne) pour devenir compatible POSIX, appelé
bosh
mais je ne suis pas au courant qu'il soit utilisé sur aucun système pour le moment. Avecksh88
ce fait un deuxième coque compatible POSIX basé sur le code de la coque Bourne4 Dans les anciennes versions, vous pouviez également utiliser
mksh
ou sonlksh
incarnation plus POSIX . C'est le shell MirOS (anciennement MirBSD) basé sur pdksh, lui-même basé sur le shell Forsyth (une autre réimplémentation du shell Bourne))la source
exec sh "$0" "$@"
après avoir défini lePATH
?sh
J'aurais pensé que cela devrait être récupéré au bon endroit.$PATH
.$(...)
, les modes emacs / vi, les extensions tilde / brace (celles initialement de csh), fc, typeset, alias , syntaxe des fonctions de style ksh ...Oui, vous pouvez l'utiliser
#!/bin/sh
dans un script car il/bin/sh
est (espérons-le) prévu sur de tels systèmes, généralement via un lien quelconque qui sebash
comporte (plus ou moins) comme lesh
ferait. Voici un système Centos7, par exemple, qui reliesh
àbash
:Vous pouvez également l'utiliser
#!/bin/bash
si vous écrivez unbash
script uniquement pour ce système et souhaitez utiliser desbash
fonctionnalités. Cependant, ces scripts souffriront de problèmes de portabilité, par exemple sur OpenBSD oùbash
n'est installé que si l'administrateur prend la peine de l'installer (je ne le fais pas) et ensuite il est installé sur/usr/local/bin/bash
, non/bin/bash
. Un#!/bin/sh
script strictement POSIX devrait être plus portable.la source
sh
, Bash passe en mode POSIX après avoir lu les fichiers de démarrage." - gnu.org/software/bash/manual/bashref.html#Bash-POSIX-Mode#!/bin/bash
précisément pour pouvoir profiter des fonctionnalités non POSIX./bin/sh
c'est un lien symbolique versbash
, n'est-ce pas? Je sais que c'est sûr sur CentOS.bash
. Le binaire sait quel nom a été utilisé pour l'invoquer, et quand il s'appelle,sh
il agit comme de la vieille Bournesh
.Tu as demandé
La réponse dépend de ce que vous écrivez dans le script shell.
Si vous utilisez strictement des scripts portables compatibles POSIX et que vous n'utilisez aucune commande spécifique à bash, vous pouvez utiliser
/bin/sh
.Si vous savez que vous ne jamais utiliser le script sur une machine avec bash, et que vous voulez utiliser la syntaxe spécifique à bash, alors vous devriez utiliser
/bin/bash
Si vous voulez être sûr que le script fonctionne sur un assortiment de machines unix, vous devez utiliser uniquement la syntaxe POSIX conforme, et
/bin/sh
Si vous utilisez régulièrement un autre shell (par exemple ksh , zsh ou tcsh ), et que vous souhaitez utiliser cette syntaxe dans votre script, vous devez utiliser l'interpréteur approprié (comme
/bin/ksh93
,/bin/zsh
ou/bin/tcsh
)la source
Le "#!" commentaire n'utilise pas toujours
/bin/bash
ou/bin/sh
. Il répertorie simplement ce que l'interprète doit être, pas seulement pour les scripts shell. Par exemple, mes scripts python commencent généralement par#!/usr/bin/env python
.Maintenant, la différence entre
#!/bin/sh
et#!/bin/bash
est que ce/bin/sh
n'est pas toujours un lien symbolique vers/bin/bash
. Souvent mais pas toujours. Ubuntu est une exception notable ici. J'ai vu des scripts fonctionner correctement sur CentOS mais échouer sur Ubuntu car l'auteur a utilisé la syntaxe spécifique à bash avec#!/bin/sh
.la source
Désolé de verser de l'eau froide sur toutes ces bonnes réponses qui disent que
/bin/sh
c'est présent dans tous les systèmes Unix - il est présent, sauf dans le système Unix le plus utilisé de tous les temps: Android.Android a son shell
/system/bin/sh
, et il n'y a généralement aucun moyen de créer un/bin/sh
lien, même sur un système enraciné (en raison de la façon dont le système est verrouillé à l'aide de selinux et des ensembles de limites de capacités (7)).Pour ceux qui diront qu'Android n'est pas conforme à POSIX: la plupart des distributions Linux et BSD ne le sont pas non plus. Et l'existence de
/bin/sh
ce chemin n'est pas imposée par la norme :la source
getconf
? Par exemple, sous Solaris 11.4, est-ce que ce serait le cas/usr/bin
? L'un dans/usr/xpg4/bin
(pour la conformité SUSv2), celui dans/usr/xpg6/bin
(pour la conformité SUSv3)?/usr/xpg7/bin
(pour SUSv4)?/bin/sh