Ressources pour la programmation shell portable

65

Quelles ressources existent pour la programmation shell portable? La solution ultime consiste à tester sur toutes les plates-formes ciblées, mais cela est rarement pratique.

La spécification POSIX / Single UNIX est un début, mais elle ne vous indique pas le niveau de prise en charge de chaque implémentation, ni les extensions communes existantes. Vous pouvez lire la documentation de chaque implémentation, mais cela prend beaucoup de temps et n'est pas tout à fait exact.

Il me semble qu'un format idéal serait une sorte de version annotée par la communauté de la spécification POSIX, où chaque fonctionnalité est annotée par son niveau de support parmi les différentes implémentations. Une telle chose existe t elle? Ou existe-t-il d'autres ressources utiles?

Par exemple, il y a les pages sur la portabilité du shell de Sven Mascheck , mais elles ne concernent que des éléments syntaxiques et quelques éléments intégrés, et ne couvrent que les anciens shells. Je cherche une ressource plus complète.

Gilles, arrête de faire le mal
la source
2
NB Veuillez ne pas répondre ici simplement pour citer le document de conformité d'une implémentation particulière. Si vous en avez un, le tag wiki correspondant serait un bon endroit.
Gilles 'SO- arrête d'être méchant'
1
Quelqu'un a besoin d'explorer l'historique de révision pour autoconfet Metaconfig(Perl, rn) et de rassembler toutes les astuces et leurs commentaires explicatifs au même endroit.
geekosaur
@geekosaur: bonne suggestion. Je n'ai jamais jeté un œil aux éléments internes de autoconf. Existe-t-il un guide pour écrire ses propres scripts? Si tel est le cas, ce serait une bonne réponse à ma question, même si elle n’est pas définitive.
Gilles 'SO- arrête d'être méchant'
5
Je suis sûr que vous pourrez le trouver facilement, mais pour le bénéfice des autres personnes qui suivent ce fil de discussion, voici un lien vers une page pertinente du manuel autoconf: gnu.org/software/hello/manual/autoconf/Portable- Shell.html
J. Taylor
1
Connexe: Comment puis-je tester la conformité POSIX des scripts shell?
Gilles, arrête de faire le mal

Réponses:

32

Le manuel autoconf contient une section sur la programmation de shell portable .

Bien que cela ne vise pas spécifiquement POSIX, il s'agit probablement de la collection la plus complète de choses à faire et à ne pas faire lorsque vous essayez d'écrire du code shell portable.

Riccardo Murri
la source
3
C’est l’une des meilleures ressources et a été construite lors de l’écriture de code dans M4 qui devait produire un code shell portable sur autant de shells que possible.
Tim Post
6

En plus de dashet posh, il y a bournesh(ou bsh), le Heirloom Bourne Shell , qui peut être utilisé pour détecter les Bashism .

Le projet Heirloom inclut également "The Heirloom Toolchest", une collection de plus de 100 utilitaires Unix standard (qui pourraient servir de point de départ pour comparer les options de ligne de commande).

ralf
la source
2
Notez que le shell Bourne n’est pas un shell POSIX. Rendre votre script portable dans un shell Bourne reviendrait à déclasser la syntaxe de votre script du langage standard POSIX sh au dénominateur commun entre celui-ci et la syntaxe du shell Bourne. Ne vaut pas l'avis sauf si vous voulez être portable sur des systèmes anciens (ou Solaris 10 et antérieur et que vous n'avez pas le choix d'utiliser le sh standard qui se trouvait dans / usr / xpg4 / bin ici).
Stéphane Chazelas
5

Semblable à cette réponse , essayez d’exécuter votre script en posh .

De plus, n'oubliez pas de définir la POSIXLY_CORRECTvariable d'environnement sur true, car de nombreux programmes (pas uniquement le shell) adhéreront plus strictement aux normes POSIX.

Philomath
la source
4

Écrire vos scripts en utilisant dash pourrait être un début.

Glenn Jackman
la source
3
Le test avec tableau de bord est le strict minimum pour éviter la dépendance accidentelle sur les caractéristiques ksh / bash, mais je suis après plus que cela: savoir au sujet des lacunes dans d' autres coquilles (par exemple la manipulation des pièges pauvres de zsh), et surtout dans les services publics shell (par exemple OpenBSD de findtoujours n'a pas été implémenté -exec +).
Gilles, arrête de faire le mal '24
FWIW, OpenBSD le findfait de -exec utility {} +nos jours.
Kusalananda
2

Dans une certaine mesure, vous pouvez essayer checkbashismsle devscriptspaquet Debian / Ubuntu .

Ce n'est pas parfait, mais cela présente l'avantage d'être un point de départ existant. Par exemple, il ne voit pas les problèmes classiques avec sed/ findconcernant les différences entre GNU et BSD / autres.

Par défaut, il est orienté Debian + tiret, le -pdrapeau peut être utile dans votre cas.

shellholic
la source
2

Aujourd'hui, vous pouvez généralement trouver un shell POSIX sur un système, ce qui signifie généralement que vous pouvez utiliser un script en langage POSIX (modulo s'exécutant avec des problèmes de conformité).

Le seul problème est que /bin/shparfois ce n’est pas un shell POSIX. Et vous devez coder en dur la #!ligne dans des scripts qui doivent se comporter comme de beaux exécutables; vous ne pouvez pas simplement demander à l'utilisateur de rechercher le problème, puis d'appeler votre script sous la forme /path/to/posix/shell myscript.

L'astuce consiste donc à utiliser les fonctionnalités POSIX dans votre script, mais à le faire rechercher automatiquement le shell POSIX. Une façon de le faire est comme ça:

#!/bin/sh

# At this point, we may be running under some old shell
# we have to tread carefully.

# note how we use test rather than [ ] syntax and avoid
# depending on test with no argument producing a failure;
# i.e. "test $posix_shell".

if ! test x$posix_shell = x ; then
  # the three possible shell paths are just an example;
  # please extend as necessary.

  for shell in /usr/xpg4/bin/sh /bin/bash /usr/bin/bash ; do
    if test -x $shell ; then
       posix_shell=$shell
    fi
  done
  if test x$posix_shell = x ; then
    echo "no POSIX shell found"
    exit 1
    # or we could avoid bailing here and just fall back on /bin/sh:
    # echo "falling back on /bin/sh: cross your fingers that it works"
    # posix_shell=/bin/sh
  fi
  export posix_shell

  # plain "$@" is broken in ancient shells! 
  # I seem to recall ${@+"$@"}: not sure if that's the right trick.

  exec $posix_shell $0 ${@+"$@"}  # can we count on exec in legacy shells? 
fi

# phew, at this point in the script we have been re-executed and are
# being interpreted by some reasonably modern shell. We can use $(...)
# command substitution, and other features.

Il existe d'autres approches, telles que la génération de code. Boostez vos scripts avec un petit script qui prend un corps de fichiers de script sans #! ligne, et ajoute un.

La pire chose à faire est de commencer à écrire des scripts entiers de manière à ce qu’ils s’exécutent sur un shell Bourne à partir de 1981. Cela n’est nécessaire que si vous devez écrire pour un système qui n’a pas vraiment d’autre shell. .

Kaz
la source