Lo tienes al revés. /bin/sh
Casi nunca es un shell Bourne en estos días, y es cuando es así que tienes un problema cuando usas un #! /bin/sh
she-bang.
El shell Bourne fue un shell escrito a finales de los años 70 y reemplazó al shell Thompson anterior (también llamado sh
). A principios de los años 80, David Korn escribió algunas extensiones para el shell Bourne, reparó algunos de los errores y torpezas de diseño (e introdujo algunos) y lo llamó el shell Korn.
A principios de los años 90, POSIX especificó el sh
lenguaje basado en un subconjunto del shell Korn y la mayoría de los sistemas ahora han cambiado /bin/sh
a Korn shell o a un shell compatible con esa especificación. En el caso de los BSD, cambiaron gradualmente su /bin/sh
, inicialmente (después de que ya no pudieron usar el shell Bourne por razones de licencia) el shell Almquist, un clon del shell Bourne con algunas extensiones ksh, por lo que se volvió compatible con POSIX.
Hoy, todos los sistemas POSIX tienen un shell llamado sh
(más a menudo, pero no necesariamente /bin
, POSIX no especifica la ruta de las utilidades que especifica) que es en su mayoría compatible con POSIX. Generalmente se basa en ksh88, ksh93, pdksh, bash, ash o zsh², pero no en el shell Bourne ya que el shell Bourne nunca fue compatible con POSIX³. Algunas de esas conchas ( bash
, zsh
, yash
y algunos pdksh
derivados permiten un modo compatible con POSIX Cuando se invoca como sh
y son menos compatible de otra manera).
bash
(la respuesta de GNU al shell Korn) es en realidad el único shell de código abierto (y se podría decir que solo se mantiene actualmente ya que los otros generalmente se basan en ksh88, que no ha recibido ninguna característica nueva desde los años 90) que ha sido certificado como ser compatible con POSIX sh
(como parte de la certificación macOS).
Cuando escribe un script con un #! /bin/sh -
she-bang, debe usar una sh
sintaxis estándar (y también debe usar la sintaxis estándar para las utilidades utilizadas en ese script si desea ser portátil, no es solo el shell lo que está involucrado al interpretar un shell script), entonces no importa qué implementación de ese sh
intérprete de sintaxis estándar se use ( ksh
, bash
...).
No importa que esos shells tengan extensiones sobre el estándar siempre que no los use. Es como escribir código C, siempre que escriba código C estándar y no use extensiones de un compilador (como gcc
) u otro, su código debe compilarse bien, independientemente de la implementación del compilador, siempre que el compilador sea compatible.
Aquí, con su #! /bin/sh
ella-bang, su problema principal sería los sistemas en los que /bin/sh
es el shell Bourne que por ejemplo no es compatible con características estándar como $((1+1))
, $(cmd)
, ${var#pattern}
... En cuyo caso es posible que necesite soluciones temporales como:
#! /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
Por cierto, Ubuntu /bin/sh
no es bash
por defecto. Es en dash
estos días, un shell basado en NetBSD sh
, basado en el shell Almquist, que en su mayoría es compatible con POSIX, excepto que no admite caracteres de varios bytes. En Ubuntu y otros sistemas basados en Debian, puede elegir entre bash
y dash
para /bin/sh
con dpkg-reconfigure dash
) 4 . sh
los scripts enviados con Debian deberían funcionar igual en ambos shells, ya que están escritos en el estándar de política de Debian (un superconjunto del estándar POSIX). Probablemente encontrará que también funcionan bien en zsh
la sh
emulación o bosh
(probablemente no, ksh93
ni los yash
que no tienen local
incorporado (requerido por la política de Debian pero no POSIX)).
Todos los sistemas en alcance en unix.stackexchange.com tienen un POSIX en sh
alguna parte. La mayoría de ellos tienen un /bin/sh
(puede encontrar algunos muy raros que no tienen un /bin
directorio pero probablemente no le importa), y eso generalmente es un sh
intérprete POSIX (y en casos raros un shell Bourne (no estándar) )
Pero sh
es el único ejecutable de intérprete de shell que puede estar seguro de encontrar en un sistema. Para los otros shells, puede estar seguro de que macOS, Cygwin y la mayoría de las distribuciones de GNU / Linux tendrán bash
. Los sistemas operativos derivados de SYSV (Solaris, AIX ...) generalmente tendrán ksh88, posiblemente ksh93. OpenBSD, MirOS tendrá una derivada pdksh. macOS tendrá zsh
. Pero fuera de eso, no habrá garantía. No hay garantía de si bash
alguno de esos otros shells se instalará en /bin
o en otro lugar (por lo general, se encuentra en /usr/local/bin
BSD cuando se instala, por ejemplo). Y, por supuesto, no hay garantía de la versión del shell que se instalará.
Tenga en cuenta que #! /path/to/executable
no es una convención , es una característica de todos los núcleos tipo Unix ( introducidos a principios de los años 80 por Dennis Ritchie ) que permite ejecutar archivos arbitrarios al especificar la ruta del intérprete en una primera línea que comienza #!
. Puede ser cualquier ejecutable.
Cuando ejecuta un archivo cuya primera línea comienza #! /some/file some-optional-arg
, el núcleo termina ejecutándose /some/file
con some-optional-arg
, la ruta del script y los argumentos originales como argumentos. Puedes hacer esa primera línea #! /bin/echo test
para ver qué está pasando:
$ ./myscript foo
test ./myscript foo
Cuando se usa en /bin/sh -
lugar de /bin/echo test
, el núcleo se ejecuta /bin/sh - ./myscript foo
, sh
interpreta el código de contenido almacenado myscript
e ignora esa primera línea, ya que es un comentario (comienza con #
).
¹ Probablemente el único sistema actual en el que cualquiera de nosotros se encontrará con un /bin/sh
shell basado en Bourne es Solaris 10. Solaris es uno de los pocos Unices que decidió mantener un shell Bourne allí para la compatibilidad con versiones anteriores (el sh
lenguaje POSIX no es completamente compatible con versiones anteriores del shell Bourne) y (al menos para las implementaciones de escritorio y servidor completo) tienen POSIX en sh
otro lugar (en /usr/xpg4/bin/sh
, basado en ksh88), pero eso cambió en Solaris 11, donde /bin/sh
ahora es ksh93. Los otros son en su mayoría difuntos.
² El /bin/sh
de MacOS / X solía serzsh
, pero luego cambió a bash
. No zsh
es el enfoque principal para ser utilizado como una sh
implementación POSIX . Su sh
modo es principalmente poder incrustar o invocar ( source
) sh
código POSIX en zsh
scripts
³ Recientemente, @schily extendió el shell OpenSolaris (basado en el shell SVR4, basado en el shell Bourne) para que sea compatible con POSIX, bosh
pero no estoy al tanto de que todavía se utiliza en ningún sistema. Junto con ksh88
eso lo convierte en un segundo shell compatible con POSIX basado en el código del shell Bourne
4 En versiones anteriores, también podría usar mksh
o su lksh
encarnación más POSIX . Ese es el shell MirOS (anteriormente MirBSD) basado en pdksh, basado en el shell Forsyth (otra reimplementación del shell Bourne)