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 certains pdksh
dérivés permettent un mode compatible POSIX lorsqu'il est invoqué comme sh
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 à POSIX sh
(dans le cadre de la certification macOS).
Lorsque vous écrivez un script avec un #! /bin/sh -
she-bang, vous devez utiliser une sh
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 cet sh
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:
#! /bin/sh -
if false ^ true; then
# in the Bourne shell, ^ is an alias for |, so false ^ true returns
# true in the Bourne shell and the Bourne shell only.
# Assume the system is Solaris 10 (older versions are no longer maintained)
# You would need to adapt if you need to support some other system
# where /bin/sh is the Bourne shell.
# We also need to fix $PATH as the other utilities in /bin are
# also ancient and not POSIX compatible.
PATH=`/usr/xpg6/bin/getconf PATH`${PATH:+:}$PATH || exit
export PATH
exec /usr/xpg4/bin/sh "$0" "$@"
# that should give us an environment that is mostly compliant
# to the Single UNIX Specification version 3 (POSIX.2004), the
# latest supported by Solaris 10.
fi
# rest of the script
Par ailleurs, Ubuntu /bin/sh
n'est pas bash
par défaut. C'est de dash
nos jours, un shell basé sur NetBSD sh
, 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 entre bash
et dash
pour /bin/sh
avec dpkg-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 dans zsh
l' sh
émulation de bosh
( ou probablement pas ksh93
et yash
qui n'ont pas de fonction local
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 un sh
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 auront bash
. 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 aura zsh
. Mais hors de cela, il n'y aura aucune garantie. Aucune garantie que ce soit bash
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
avec some-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:
$ ./myscript foo
test ./myscript foo
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é dans myscript
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 (le sh
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 POSIX sh
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é en bash
. Ce n'est pas zsh
l'objectif principal d'être utilisé comme une sh
implémentation POSIX . Son sh
mode est avant tout de pouvoir embarquer ou appeler ( source
) du sh
code POSIX dans des zsh
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. Avec ksh88
ce fait un deuxième coque compatible POSIX basé sur le code de la coque Bourne
4 Dans les anciennes versions, vous pouviez également utiliser mksh
ou son lksh
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))