2011-10-19 6 views
7

Accidentalmente comencé un script bash con $! en lugar de #! y obtuve un comportamiento muy extraño. Estoy intentando descubrir qué pasó.

Si intenta este script:

$!/bin/bash 
echo Hello world! 

obtendrá el siguiente comportamiento:

$ chmod +x hello 
$ ./hello 
[nothing happens, get prompt back] 
$ exit 
exit 
Hello world! 
$ 

lo que parece que esto sucedió:

  1. Una nueva cáscara del golpe generó.
  2. Al salir, se ejecuta el resto del script.

¿Qué pasa? ¿Cómo está sucediendo algo? Sin #!, ¿cómo sabe el shell usar bash para interpretar el script?

Obviamente se trata de una pregunta de "satisfacer mi curiosidad" en lugar de "resolver mi problema". Google no rinde mucho, probablemente porque #! y $! en las consultas no hacen feliz al robot de Google.

Respuesta

9

$ algo es un parámetro ("variable") expansión, pero $! en particular, devuelve un valor que no se encuentra en la secuencia de comandos, por lo se expande como una cadena de longitud cero.

lo tanto, su guión es, estás en lo correcto, el equivalente a:

/bin/bash 
echo Hello world! 

El shebang magic number es una característica antigua de Unix, pero la cáscara es aún más antigua. Un subshell ejecuta un archivo de texto con el bit de ejecución establecido que el kernel no puede ejecutar (porque no está realmente compilado). Es decir, el shell ejecuta deliberadamente otro shell y pasa el nombre de ruta como parámetro. Así es como se escribieron los comandos escritos como scripts de shell antes de que se inventara shebang, y aún está allí en el código.

3

Expandiendo un poco la respuesta de @DigitalRoss :.

un script ejecutable sin #! en la primera línea es ejecutado por /bin/sh - incluso si se ejecuta desde bash (o tcsh). Esto no es funcionalidad de shell, está en el núcleo.

Así que cuando ejecutó su script, fue ejecutado por /bin/sh (lo que significa, en la mayoría de los sistemas, que no podrá usar funciones específicas de bash), $! expandido a nada (porque ese shell no tiene inició cualquier proceso en segundo plano) y la primera línea invoca un shell interactivo/bin/bash. A continuación, sale de ese shell interactivo y su secuencia de comandos ejecuta la línea echo Hello world! y finaliza, volviendo a colocarlo en el shell original.

Por ejemplo, si cambia a echo Hello world!echo $BASH_VERSION, usted encontrará que no se imprime nada - y si escribe history de la cáscara del golpe interactiva invocado, no se mostrará nada.

Cuestiones relacionadas