2012-09-06 22 views
20

estaba escribiendo un simple script de shell y descubrí que mi script no requiere línea tinglado¿La secuencia de comandos Shell funciona bien sin la línea shebang? ¿Por qué?

#!/bin/sh 

Si reparto entre los permisos de ejecución a mi guión y ejecutar utilizando ./myscript.sh. Funciona bien

Estoy usando bash shell y /bin/sh apuntando realmente a bash.

lrwxrwxrwx 1 root root /bin/sh -> bash 

sé que la línea tinglado se utiliza contar cáscara que interprete a utilizar para su resto de la secuencia de comandos.

Si echo de menos la línea shebang en perl, concedo permisos de ejecución y ejecuto ./myscript.pl, no funciona.

¿Qué está pasando realmente aquí? Si uso ./, ¿cuándo se necesita realmente la línea shebang? Se necesita

Respuesta

14

línea tinglado en el archivo y sólo si se supone que debe ser ejecutado como ejecutable (en contraposición a sh file.sh invocación. No es realmente necesario por el guión, que es para el sistema de saber cómo encontrar intérprete.

EDITAR:. lo siento por la mala interpretación de la pregunta Si la línea tinglado no se encuentra o no se reconoce, se utiliza /bin/sh pero prefiero ser explícito sobre el intérprete

Tenga en cuenta, que este comportamiento no es universal,.. IIRC, solo algunos exec* función familiar hacen eso (no t o mencionar diferentes plataformas), entonces esa es otra razón para ser explícito aquí.

+2

El OP dice que invoca el script como './Myscript.sh' - Supongo que eso significa que no está utilizando explícitamente el shell como ejecutable y el script como argumento. –

+0

sí. Pero el script se está ejecutando sin esa línea? ¿Por qué? Estoy usando './Myscript.sh' para ejecutar script. –

+0

Vaya. Editado la respuesta, gracias. –

13

El shell principal, donde ingresó ./myscript.sh, primero intentó execve, que es donde la línea shebang entraría en vigor si estuviera presente. Cuando esto funciona, el padre desconoce la diferencia entre los scripts y los ELF porque el kernel se ocupa de ello.

Falló el execve, por lo que se activó una antigua característica de compatibilidad de Unix, anterior a la existencia de líneas de shebang. Adivinó que un archivo que tiene permiso de ejecución pero no es reconocido como un archivo ejecutable válido por el kernel debe ser un script de shell.

Por lo general, el shell padre adivina que el script está escrito para el mismo shell (mínimos shells como Bourne ejecutan el script con /bin/sh, bash lo ejecuta como un subproceso bash), csh hace algunas conjeturas más complejas basadas en el primero personaje porque es anterior a shebang también y necesitaba coexistir con el shell de Bourne).

Necesita una línea shebang cuando sabe que estas suposiciones serán incorrectas (por ejemplo, con shebang es #!/usr/bin/perl), o cuando no confía en que las suposiciones funcionen de manera consistente, o cuando la secuencia de comandos necesite ser ejecutada por un proceso principal que no es un shell en sí mismo.

+1

Más información se puede encontrar en la respuesta a * ¿Por qué algunos scripts comienzan con #! ...? * pregunta en http://www.faqs.org/faqs/unix-faq/faq/part3/section-16.html –

3

El POSIX (4 Single UNIX Specification) estándar no es útil: "! #"

Si la primera línea de un archivo de comandos de shell se inicia con los personajes , los resultados no están especificados

Por lo tanto, el estándar implica que si no tiene #!entonces debería ejecutar un shell POSIX. Pero las conchas modernas no son compatibles con POSIX. El viejo Korn Shell 88 (ksh88) ejecutó el shell Bourne (cerca de un shell POSIX) sin #! línea, pero ksh93 rompe eso, y también lo hace Bash. Con ambos ksh93 y Bash, ¡ejecutan su propio shell si no #! línea está presente.

A pesar de la opinión popular, los proyectiles Bash y Korn son diferentes. Cuando escribe un script de shell, nunca puede estar seguro de qué shell se ejecutará, o incluso si se ejecutará desde otro shell en absoluto (la mayoría de los lenguajes de programación pueden ejecutar otros programas). En el momento en que use algo fuera de la sintaxis de Bourne/POSIX, se lo descartará.

Siempre use un #! línea, no lo dejes al azar.

+2

Su afirmación sobre el cumplimiento del shell se revierte. Los shells modernos como ksh y bash son compatibles con POSIX (o al menos muy cerca de) mientras que el shell Bourne definitivamente no lo es. El estándar POSIX inicial para el shell era esencialmente ksh88. Eso hace que razonable para bash y ksh para ejecutarse a sí mismos cuando el estándar indica que se debe utilizar un shell compatible con POSIX. Bash, ksh88 y ksh93 difieren definitivamente, pero las áreas donde lo hacen son comportamientos no especificados en el estándar o fuera de su alcance. – jlliagre

+0

@jlliagre: POSIX dice 'sh' se ejecuta si no hay' #! ', No ksh o bash. Cuando Bash ejecuta un no- #! el script de línea no se ejecuta en modo POSIX (--posix) o como el enlace simbólico sh. POSIX podría haberse basado en ksh88, pero mencioné específicamente ksh93, que es considerablemente diferente de sh en el estándar POSIX (también existen diferencias entre ksh88 y POSIX, typedef en funciones, por ejemplo), sin embargo, es cierto que, SFAIK, ksh93 es un superconjunto de POSIX sh (por eso typedef en funciones cambió de ksh88 a 93). Estoy de acuerdo con mi consejo de que es aconsejable especificar siempre una línea '#!'. – cdarke

+1

Asume incorrectamente que/bin/sh siempre es POSIX. POSIX no dice/bin/sh se ejecuta cuando no hay shebang, pero cuando ya se encuentra en un entorno POSIX, un shell POSIX interpretará un script sin shebang. No exige que este shell tenga un nombre de ruta particular. Depende del implementador definir su nombre (probablemente sh) y la ruta que podría no ser/bin como Solaris 10/usr/xpg4/bin. Es por eso que recomiendo los scripts de shell portátiles para no tener un shebang, como sugiere el estándar. ¡Si tu caparazón funciona como modo POSIX y llamas a un no #! script, también se ejecutará en modo POSIX. – jlliagre

Cuestiones relacionadas