Dado que el archivo no es de ninguno de los tipos de ejecutables reconocidos por el sistema, y suponiendo que tenga el permiso para ejecutar ese archivo, la execve()
llamada al sistema generalmente fallará con un error ENOEXEC
( no ejecutable ).
Lo que sucede entonces depende de la aplicación y / o función de biblioteca utilizada para ejecutar el comando.
Puede ser, por ejemplo, un shell, la función execlp()
/ execvp()
libc.
La mayoría de las otras aplicaciones usarán cualquiera de ellas cuando ejecuten un comando. Invocarán un shell, por ejemplo, mediante la system("command line")
función libc, que normalmente invocará sh
para analizar esa línea de comando (cuya ruta se puede determinar en el momento de la compilación (como /bin/sh
vs /usr/xpg4/bin/sh
en Solaris)), o invocará el shell almacenado $SHELL
por ellos mismos como vi
con su !
comando, xterm -e 'command line'
y muchos otros comandos ( su user -c
invocarán el shell de inicio de sesión del usuario en lugar de $SHELL
).
En general, un archivo de texto sin shebang que no comienza #
se considera un sh
script. Sin sh
embargo, cuál es variará.
execlp()
/ execvp()
, al execve()
regresar ENOEXEC
normalmente invocará sh
en él. Para los sistemas que tienen más de uno sh
porque pueden ajustarse a más de un estándar, lo sh
que se determinará generalmente en el momento de la compilación (de la aplicación usando execvp()
/ execlp()
mediante la vinculación de un blob de código diferente que se refiere a una ruta diferente a sh
). Por ejemplo, en Solaris, será /usr/xpg4/bin/sh
(un estándar, POSIX sh
) o /bin/sh
(el shell Bourne (un shell anticuado) en Solaris 10 y versiones anteriores, ksh93 en Solaris 11).
Cuando se trata de conchas, hay mucha variación. bash
, AT&T ksh
, el shell Bourne generalmente interpretará la secuencia de comandos ellos mismos (en un proceso secundario a menos que exec
se use) después de haber simulado un execve()
, que desarma todas las variables no exportadas, cierra todos los archivos close-on-exec, elimina todas las trampas personalizadas, alias, funciones ... ( bash
interpretará el script en sh
modo). yash
se ejecutará en sí (con sh
como argv[0]
lo que en sh
modo) para interpretarlo.
zsh
, pdksh
, ash
Cáscaras basados típicamente invocar sh
(el camino de los cuales determina en tiempo de compilación).
Para csh
y tcsh
(y el sh
de algunos BSD anteriores), si el primer carácter del archivo es #
, entonces se ejecutarán para interpretarlo, y de lo sh
contrario. Eso se remonta a un tiempo anterior al shebang donde csh
reconocía #
como comentarios pero no el shell Bourne, por lo que #
era una pista de que era un script csh.
fish
(al menos la versión 2.4.0), solo devuelve un error si execve()
falla (no intenta tratarlo como un script).
Algunos shells (como bash
AT&T ksh
) primero intentarán determinar heurísticamente si el archivo probablemente sea un script o no. Por lo tanto, es posible que algunos shells se nieguen a ejecutar un script si tiene un carácter NUL en los primeros bytes.
También tenga en cuenta que si execve()
falla con ENOEXEC pero el archivo tiene una línea shebang, algunos shells intentan interpretar esa línea shebang ellos mismos.
Entonces, algunos ejemplos:
- Cuando
$SHELL
es /bin/bash
, xterm -e 'myscript with args'
habrá myscript
interpretado por bash
en sh
modo. Mientras que con xterm -e myscript with args
, xterm
se usará execvp()
para que el guión sea interpretado por sh
.
su -c myscript
en Solaris 10 donde root
el shell de inicio de sesión es /bin/sh
y /bin/sh
es el shell Bourne lo habrá myscript
interpretado el shell Bourne.
/usr/xpg4/bin/awk 'BEGIN{system("myscript")'
en Solaris 10 lo tendrá interpretado por /usr/xpg4/bin/sh
(lo mismo para /usr/xpg4/bin/env myscript
).
find . -prune -exec myscript {} \;
en Solaris 10 (usando execvp()
) lo interpretará /bin/sh
incluso con /usr/xpg4/bin/find
, incluso en un entorno POSIX (un error de conformidad).
csh -c myscript
lo interpretará csh
si comienza con #
, de lo sh
contrario.
Con todo, no puede estar seguro de qué shell se usará para interpretar ese script si no sabe cómo y por qué se invocará.
En cualquier caso, read -p
es una bash
sintaxis única, por lo que querrá asegurarse de que el script sea interpretado por bash
(y evitar esa .sh
extensión engañosa ). O conoce la ruta del bash
ejecutable y usa:
#! /path/to/bash -
read -p ...
O puede intentar confiar en una $PATH
búsqueda del bash
ejecutable (suponiendo que bash
esté instalado) usando:
#! /usr/bin/env bash
read -p ...
(se env
encuentra casi en todas partes /usr/bin
). Alternativamente, puede hacer que sea POSIX + Bourne compatible, en cuyo caso puede usar /bin/sh
. Todos los sistemas tendrán a /bin/sh
. En la mayoría de ellos será (en su mayor parte) compatible con POSIX, pero aún puede encontrar de vez en cuando un shell Bourne allí.
#! /bin/sh -
printf >&2 'Enter a user name: '
read user
printf '%s\n' "$user"