Recursos para la programación de shell portátil

65

¿Qué recursos existen para la programación de shell portátil? La respuesta final es probar en todas las plataformas específicas, pero eso rara vez es práctico.

La especificación POSIX / Single UNIX es un comienzo, pero no le dice cuál es el nivel de soporte de cada implementación ni qué extensiones comunes existen. Puede leer la documentación de cada implementación, pero eso lleva mucho tiempo y no es completamente preciso.

Me parece que un formato ideal sería algún tipo de versión anotada por la comunidad de la especificación POSIX, donde cada característica está anotada por su nivel de soporte entre las diferentes implementaciones. ¿Hay tal cosa? ¿O hay otros recursos útiles?

Por ejemplo, hay páginas de portabilidad de shell de Sven Mascheck , pero solo se trata de elementos sintácticos y algunos elementos incorporados, y solo cubre shells antiguos. Estoy buscando un recurso más completo.

Gilles 'SO- deja de ser malvado'
fuente
2
Nota: no responda aquí solo para citar el documento de conformidad de una implementación en particular. Si tiene uno de esos, la etiqueta wiki correspondiente sería un buen lugar.
Gilles 'SO- deja de ser malvado'
1
Alguien necesita extraer el historial de revisiones para autoconfy Metaconfig(Perl, rn) y recopilar todos los trucos y sus comentarios explicativos en un solo lugar.
geekosaur
@geekosaur: Buena sugerencia. Nunca he visto los aspectos internos de autoconf, ¿hay algo que uno pueda usar como guía al escribir los propios scripts? Si es así, esta sería una buena respuesta a mi pregunta, incluso si no es definitiva.
Gilles 'SO- deja de ser malvado'
55
Estoy seguro de que ambos podrían encontrarlo fácilmente, pero para el beneficio de otras personas que siguen este hilo, aquí hay un enlace a una página relevante del manual de autoconf: gnu.org/software/hello/manual/autoconf/Portable- Shell.html
J. Taylor
1
Relacionado: ¿Cómo puedo probar el cumplimiento de POSIX para los scripts de shell?
Gilles 'SO- deja de ser malvado'

Respuestas:

32

El manual de autoconf tiene una sección sobre programación de shell portátil .

Aunque eso no está dirigido específicamente a POSIX, es probablemente la colección más completa de qué hacer y qué no hacer al intentar escribir código shell portátil.

Riccardo Murri
fuente
3
Ese es uno de los mejores recursos y se creó al escribir código en M4 que tenía que producir código de shell que fuera portátil en la mayor cantidad posible de shells.
Tim Post
6

Además de dashy posh, hay bournesh(o bsh), Heirloom Bourne Shell , que se puede usar para detectar Bashisms .

The Heirloom Project también incluye "The Heirloom Toolchest", una colección de más de 100 utilidades estándar de Unix (que podría servir como punto de partida para comparar las opciones de la línea de comandos).

ralf
fuente
2
Tenga en cuenta que el shell Bourne no es un shell POSIX, hacer que su script sea portátil al shell Bourne significaría degradar la sintaxis de su script desde el lenguaje estándar POSIX sh al denominador común entre eso y la sintaxis del shell Bourne. No vale la pena la opinión a menos que desee ser portátil para sistemas antiguos (o Solaris 10 y anteriores y no tiene la opción de usar el sh estándar que estaba en / usr / xpg4 / bin allí).
Stéphane Chazelas
5

Similar a esta respuesta , intente ejecutar su script en elegante .

Además, no olvide establecer la POSIXLY_CORRECTvariable de entorno en true, ya que esto hace que muchos programas (no solo el shell) se adhieran más estrictamente a los estándares POSIX.

Philomath
fuente
4

Escribir sus scripts usando guión podría ser un comienzo.

Glenn Jackman
fuente
3
Las pruebas con dash son lo mínimo para evitar la dependencia accidental de las funciones ksh / bash, pero busco más que eso: conocer las deficiencias en otros shells (por ejemplo, el mal manejo de trampas de zsh) y, sobre todo, en las utilidades de shell (por ejemplo, OpenBSD findtodavía no ha implementado -exec +).
Gilles 'SO- deja de ser malvado'
FWIW, OpenBSD lo findhace -exec utility {} +hoy en día.
Kusalananda
2

Hasta cierto punto, puede probar checkbashismsen el devscriptspaquete Debian / Ubuntu .

No es perfecto, pero tiene el beneficio de ser un punto de partida existente. Por ejemplo, no ve las fallas clásicas con sed/ con findrespecto a GNU vs BSD / otras diferencias.

Por defecto, está orientado a Debian + dash, el -pindicador puede ser útil en su caso.

concha
fuente
2

Hoy en día, generalmente puede encontrar un shell POSIX en un sistema, y ​​eso generalmente significa que puede escribir en el lenguaje POSIX (módulo con errores de cumplimiento).

El único problema es que a /bin/shveces no es un shell POSIX. Y debe codificar la #!línea en scripts que se comporten como buenos ejecutables; no puede simplemente pedirle al usuario que investigue el problema y luego invoque su script como /path/to/posix/shell myscript.

Por lo tanto, el truco es utilizar las funciones POSIX en su script, pero hacer que el script encuentre automáticamente el shell POSIX. Una forma de hacerlo es así:

#!/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.

Existen otros enfoques, como la generación de código. Boostrap sus scripts con un pequeño script que toma un cuerpo de archivos de script sin un # línea, y agrega uno.

Lo peor que puede hacer es comenzar a escribir scripts completos de tal manera que se ejecuten en un shell Bourne desde 1981. Esto solo es necesario si debe escribir para un sistema que realmente no tiene ningún otro shell .

Kaz
fuente