En informática , un shebang es la secuencia de caracteres que consta del signo de número de caracteres y el signo de exclamación ( #! ) Al comienzo de un guión . También se le llama sha-bang , [1] [2] hashbang , [3] [4] pound-bang , [5] [6] o hash-pling . [7]
Cuando se usa un archivo de texto con un shebang como si fuera un ejecutable en un sistema operativo similar a Unix, el mecanismo de carga del programa analiza el resto de la línea inicial del archivo como una directiva de intérprete . El cargador ejecuta el programa intérprete especificado y le pasa como argumento la ruta que se utilizó inicialmente al intentar ejecutar el script, de modo que el programa pueda utilizar el archivo como datos de entrada. [8] Por ejemplo, si una secuencia de comandos se nombra con la ruta ruta / a / secuencia de comandos , y comienza con la siguiente línea #!/bin/sh
, entonces el cargador de programas debe ejecutar el programa / bin / sh , pasando la ruta / a / secuencia de comandos como primer argumento. En Linux , este comportamiento es el resultado tanto del kernel como del código de espacio de usuario. [9]
El intérprete suele ignorar la línea shebang, porque el carácter "#" es un marcador de comentario en muchos lenguajes de programación; Algunos intérpretes de idiomas que no usan la marca de almohadilla para comenzar los comentarios aún pueden ignorar la línea shebang en reconocimiento de su propósito. [10]
Sintaxis
La forma de una directiva de intérprete shebang es la siguiente: [8]
#! intérprete [ opcional-arg ]
en el que el intérprete es generalmente una ruta absoluta a un programa ejecutable. El argumento opcional es una cadena que representa un solo argumento. Espacio en blanco después #! es opcional.
En Linux , el archivo especificado por el intérprete se puede ejecutar si tiene el derecho de ejecución y contiene código que el kernel puede ejecutar directamente, si tiene un contenedor definido para él a través de sysctl (como para ejecutar binarios Microsoft .exe usando wine ), o si contiene un shebang. En Linux y Minix , un intérprete también puede ser un script. Una cadena de shebangs y envoltorios produce un archivo directamente ejecutable que obtiene los scripts encontrados como parámetros en orden inverso. Por ejemplo, si el archivo / bin / A es un archivo ejecutable en formato ELF , el archivo / bin / B contiene el parámetro shebang #! / Bin / A optparam y el archivo / bin / C contiene el shebang #! / Bin / B , entonces la ejecución de archivo / bin / C resuelve / bin / B / bin / C , que finalmente tiene por / bin / a optparam / bin / B / bin / C .
En los sistemas operativos derivados de Solaris y Darwin (como macOS ), el archivo especificado por el intérprete debe ser un binario ejecutable y no puede ser en sí mismo un script. [11]
Ejemplos de
Algunas líneas típicas de shebang:
#!/bin/sh
- Ejecute el archivo utilizando el shell Bourne , o un shell compatible, que se supone que está en el directorio / bin.#!/bin/bash
- Ejecuta el archivo usando el shell Bash#!/usr/bin/pwsh
- Ejecutar el archivo usando PowerShell#!/usr/bin/env python3
- Ejecutar con un intérprete de Python , usando la ruta de búsqueda del programa env para encontrarlo#!/bin/false
- No hacer nada, pero devolver un estado de salida distinto de cero , lo que indica falla. Se utiliza para evitar la ejecución autónoma de un archivo de script destinado a ejecutarse en un contexto específico, como mediante el.
comando de sh / bash,source
de csh / tcsh o como un archivo .profile, .cshrc o .login.
Las líneas Shebang pueden incluir opciones específicas que se pasan al intérprete. Sin embargo, las implementaciones varían en el comportamiento de análisis de las opciones; para la portabilidad, solo se debe especificar una opción sin ningún espacio en blanco incrustado. A continuación, se encuentran más pautas de portabilidad.
Propósito
Las directivas de intérprete permiten utilizar scripts y archivos de datos como comandos, ocultando los detalles de su implementación a los usuarios y otros programas, al eliminar la necesidad de prefijar los scripts con su intérprete en la línea de comandos.
Un script de shell Bourne que se identifica por la ruta some / path / to / foo , tiene la línea inicial,
#! / bin / sh -x
y se ejecuta con la barra de parámetros y baz como
algunos / ruta / a / foo bar baz
proporciona un resultado similar al de haber ejecutado la siguiente línea de comando en su lugar:
/ bin / sh -x algunos / ruta / a / foo bar baz
Si / bin / sh especifica el shell Bourne , entonces el resultado final es que todos los comandos del shell en el archivo some / path / to / foo se ejecutan con las variables posicionales $ 1 y $ 2 con los valores bar y baz , respectivamente. Además, debido a que el signo de número inicial es el carácter utilizado para introducir comentarios en el lenguaje shell Bourne (y en los idiomas que entienden muchos otros intérpretes), el intérprete ignora toda la línea shebang.
Sin embargo, depende del intérprete ignorar la línea shebang; por lo tanto, un script que consta de las siguientes dos líneas simplemente hace eco de ambas líneas en la salida estándar cuando se ejecuta:
#! / bin / cat¡Hola Mundo!
Fortalezas
En comparación con el uso de listas de asociación global entre las extensiones de archivo y las aplicaciones de interpretación, el método de la directiva de intérprete permite a los usuarios utilizar intérpretes no conocidos a nivel de sistema global y sin derechos de administrador. También permite la selección específica del intérprete, sin sobrecargar el espacio de nombres de la extensión del nombre de archivo (donde una extensión de archivo se refiere a más de un tipo de archivo), y permite cambiar el lenguaje de implementación de un script sin cambiar su sintaxis de invocación por otros programas. Los invocadores del script no necesitan saber cuál es el lenguaje de implementación, ya que el propio script es responsable de especificar el intérprete a utilizar.
Portabilidad
Ubicación del programa
Shebangs debe especificar rutas absolutas (o rutas relativas al directorio de trabajo actual) a los ejecutables del sistema; esto puede causar problemas en sistemas que tienen un diseño de sistema de archivos no estándar. Incluso cuando los sistemas tienen rutas bastante estándar, es muy posible que las variantes del mismo sistema operativo tengan diferentes ubicaciones para el intérprete deseado. Python , por ejemplo, podría estar en / usr / bin / python3 , / usr / local / bin / python3 , o incluso algo como / home / username / bin / python3 si lo instala un usuario normal.
Existe un problema similar para el shell POSIX , ya que POSIX solo requería que su nombre fuera sh , pero no exigía una ruta. Un valor común es / bin / sh , pero algunos sistemas como Solaris tienen el shell compatible con POSIX en / usr / xpg4 / bin / sh . [12] En muchos sistemas Linux , / bin / sh es un enlace duro o simbólico a / bin / bash , el shell Bourne Again (BASH). El uso de sintaxis específica de bash mientras se mantiene un shebang que apunta a sh tampoco es portátil. [13]
Debido a esto, a veces es necesario editar la línea shebang después de copiar un script de una computadora a otra porque la ruta que se codificó en el script puede no aplicarse en una nueva máquina, dependiendo de la coherencia en la convención anterior de colocación del intérprete. . Por esta razón y debido a que POSIX no estandariza los nombres de las rutas, POSIX no estandariza la función. [14] La herramienta GNU Autoconf puede probar el soporte del sistema con la macro AC_SYS_INTERPRETER. [15]
A menudo, el programa / usr / bin / env se puede utilizar para eludir esta limitación introduciendo un nivel de indirección . #!
es seguido por / usr / bin / env , seguido del comando deseado sin la ruta completa, como en este ejemplo:
#! / usr / bin / env sh
Esto funciona principalmente porque el camino / usr / bin / env se usa comúnmente para utilidad env , e invoca la primera sh que se encuentra en el $ PATH del usuario , normalmente / bin / sh .
Esto todavía tiene algunos problemas de portabilidad con OpenServer 5.0.6 y Unicos 9.0.2 que solo tienen / bin / env y no / usr / bin / env .
Interpretación de personajes
Otro problema de portabilidad es la interpretación de los argumentos de los comandos. Algunos sistemas, incluido Linux, no dividen los argumentos; [16] por ejemplo, cuando se ejecuta el script con la primera línea como,
#! / usr / bin / env python3 -c
todo el texto después del primer espacio se trata como un solo argumento, es decir, se python3 -c
pasará como un argumento a / usr / bin / env , en lugar de dos argumentos. Cygwin también se comporta de esta manera.
Las invocaciones de intérpretes complejas son posibles mediante el uso de un contenedor adicional . FreeBSD 6.0 (2005) introdujo un -S opción a su env ya que cambió el comportamiento de lectura de shebang a no dividir. Esta opción dice env para dividir la cadena en sí. [17] El GNU La utilidad env desde coreutils 8.30 (2018) también incluye esta característica. [18] Aunque el uso de esta opción mitiga el problema de portabilidad en el extremo del kernel con la división, agrega el requisito de que env admite esta extensión en particular.
Otro problema son los scripts que contienen un carácter de retorno de carro inmediatamente después de la línea shebang, quizás como resultado de haber sido editados en un sistema que usa saltos de línea DOS , como Microsoft Windows . Algunos sistemas interpretan el carácter de retorno de carro como parte del comando del intérprete , lo que genera un mensaje de error. [19]
número mágico
El shebang es en realidad una instancia legible por humanos de un número mágico en el archivo ejecutable, la cadena de bytes mágicos es0x23 0x21 , la codificación de dos caracteres en ASCII de #! . Este número mágico es detectado por la familia de funciones " exec ", que determina si un archivo es un script o un binario ejecutable. La presencia del shebang dará como resultado la ejecución del ejecutable especificado, generalmente un intérprete para el lenguaje del script. Se ha afirmado [20] que algunas versiones antiguas de Unix esperan que el shebang normal sea seguido por un espacio y una barra inclinada ( #! /
), pero esto parece no ser cierto; [21] más bien, los espacios en blanco después del shebang se han permitido tradicionalmente y, a veces, se han documentado con un espacio (consulte el correo electrónico de 1980 en la sección de historial a continuación).
Los caracteres shebang están representados por los mismos dos bytes en codificaciones ASCII extendidas , incluido UTF-8 , que se usa comúnmente para scripts y otros archivos de texto en sistemas actuales similares a Unix. Sin embargo, los archivos UTF-8 pueden comenzar con la marca de orden de bytes (BOM) opcional ; si la función "exec" detecta específicamente los bytes 0x23 y 0x21, entonces la presencia de la lista de materiales ( 0xEF 0xBB 0xBF ) antes del shebang evitará que se ejecute el intérprete de script. Algunas autoridades recomiendan no utilizar la marca de orden de bytes en scripts POSIX (tipo Unix), [22] por esta razón y por cuestiones filosóficas y de interoperabilidad más amplias. Además, una marca de orden de bytes no es necesaria en UTF-8, ya que la codificación no tiene problemas de endianidad ; solo sirve para identificar la codificación como UTF-8.
Etimología
Un archivo ejecutable que comienza con una directiva de intérprete se denomina simplemente script, a menudo precedido por el nombre o la clasificación general del intérprete previsto. El nombre shebang para los dos caracteres distintivos puede provenir de una contracción inexacta de SHArp bang o haSH bang , en referencia a los dos nombres típicos de Unix para ellos. Otra teoría sobre el sh in shebang es que proviene del shell predeterminado sh , generalmente invocado con shebang. [23] Este uso estaba vigente en diciembre de 1989, [24] y probablemente antes.
Historia
Dennis Ritchie introdujo el tema entre las ediciones 7 y 8 en Bell Laboratories. También se agregó a las versiones BSD de Computer Science Research de Berkeley (presente en 2.8BSD [25] y activado por defecto por 4.2BSD). Como AT&T Bell Laboratories Edition 8 Unix, y ediciones posteriores, no se lanzaron al público, la primera aparición ampliamente conocida de esta función fue en BSD.
La falta de una directiva de intérprete, pero soporte para scripts de shell, es evidente en la documentación de la Versión 7 de Unix en 1979, [26] que describe en cambio una instalación del shell Bourne donde los archivos con permiso de ejecución serían manejados especialmente por el shell. lo cual (a veces dependiendo de los caracteres iniciales del script, como ":" o "#") generaría una subcapa que interpretaría y ejecutaría los comandos contenidos en el archivo. En este modelo, los scripts solo se comportarían como otros comandos si se llamaran desde un shell de Bourne. Un intento de ejecutar directamente dicho archivo a través de la trampa del sistema exec () del sistema operativo fallaría, lo que evitaría que los scripts se comporten de manera uniforme como los comandos normales del sistema.
En versiones posteriores de sistemas similares a Unix, se eliminó esta inconsistencia. Dennis Ritchie introdujo el soporte del kernel para las directivas de intérprete en enero de 1980, para la versión 8 de Unix , con la siguiente descripción: [25]
Desde uucp Jue 10 Ene 01:37:58 1980> Desde dmr Thu Jan 10 04:25:49 1980 alejado de la investigaciónSe ha cambiado el sistema de modo que si se ejecuta un archivocomienza con los personajes mágicos #! , el resto de la línea se entiendepara ser el nombre de un intérprete para el archivo ejecutado.Anteriormente (y de hecho todavía) el shell hacía gran parte de este trabajo;se ejecutó automáticamente en un archivo de texto con modo ejecutablecuando el nombre del archivo de texto se escribió como un comando.Poner la instalación en el sistema da lo siguientebeneficios.1) Hace que los scripts de shell se parezcan más a archivos ejecutables reales,porque pueden ser el tema de 'ejecutivo'.2) Si hace un 'ps' mientras se ejecuta un comando de este tipo, es realaparece el nombre en lugar de 'sh'.Asimismo, la contabilidad se realiza sobre la base del nombre real.3) Los scripts de Shell se pueden establecer como ID de usuario . [a]4) Es más sencillo disponer de carcasas alternativas;por ejemplo, si le gusta el csh de Berkeley, no hay duda sobrequé shell debe interpretar un archivo.5) Permitirá que otros intérpretes se adapten mejor.Para aprovechar esta maravillosa oportunidad,poner #! / bin / sh en el margen izquierdo de la primera línea de sus scripts de shell.¡Espacios en blanco después! están bien. Utilice un nombre de ruta completo (no se realiza ninguna búsqueda).Por el momento, toda la línea está restringida a 16 caracteres, peroeste límite se elevará.
Sin embargo, el creador de la función no le dio un nombre: [28]
De: "Ritchie, Dennis M (Dennis) ** CTR **" Para: <[redactado] @ talisman.org >Fecha: jue, 19 de noviembre de 2009 18:37:37 -0600 Asunto: RE: ¿Qué qué -you- llaman su ! # línea? No puedo recordar que alguna vez le dimos un nombre propio.Era bastante tarde para que entrara, creo queobtuve la idea de alguien en una de las conferencias de UCBen Berkeley Unix; Puede que haya sido uno de los primeros enrealmente instalarlo, pero fue una idea que obtuvede otro lugar.En cuanto al nombre: probablemente algo descriptivo como"hash-bang", aunque tiene un sabor específicamente británico, peroen cualquier caso, no recuerdo haber usado particularmente un nombre de mascotapara la construccion.
El soporte del kernel para las directivas de intérprete se extendió a otras versiones de Unix, y se puede ver una implementación moderna en el código fuente del kernel de Linux en fs / binfmt_script.c . [29]
Este mecanismo permite que los scripts se utilicen en prácticamente cualquier contexto que puedan ser los programas compilados normales, incluso como programas de sistema completo, e incluso como intérpretes de otros scripts. Sin embargo, como advertencia, algunas versiones anteriores del soporte del kernel limitaban la longitud de la directiva del intérprete a aproximadamente 32 caracteres (solo 16 en su primera implementación), no podían dividir el nombre del intérprete de ningún parámetro en la directiva o tenían otras peculiaridades . Además, algunos sistemas modernos permiten que todo el mecanismo esté restringido o deshabilitado por motivos de seguridad (por ejemplo, el soporte de set-user-id se ha deshabilitado para scripts en muchos sistemas).
Tenga en cuenta que, incluso en sistemas con soporte completo del kernel para #! número mágico , algunos scripts que carecen de directivas de intérprete (aunque por lo general todavía requieren permiso de ejecución) todavía se pueden ejecutar en virtud del manejo de scripts heredados del shell Bourne, todavía presente en muchos de sus descendientes modernos. Luego, los scripts son interpretados por el shell predeterminado del usuario.
Ver también
- binfmt_misc
- CrunchBang Linux
- Asociación de archivos
- Fragmento de URI
Notas
- ^ La función setuid se desactiva en la mayoría de los sistemas operativos modernos después de darse cuenta de quese puede aprovecharuna condición de carrera para cambiar el script mientras se procesa. [27]
Referencias
- ^ "Guía avanzada de secuencias de comandos de Bash: Capítulo 2. Comenzando con un Sha-Bang" . Archivado desde el original el 10 de diciembre de 2019 . Consultado el 10 de diciembre de 2019 .
- ^ Cooper, Mendel (5 de noviembre de 2010). Guía avanzada de secuencias de comandos de Bash 5.3 Volumen 1 . lulu.com. pag. 5. ISBN 978-1-4357-5218-4.
- ^ MacDonald, Matthew (2011). HTML5: El manual perdido . Sebastopol, California: O'Reilly Media . pag. 373. ISBN 978-1-4493-0239-9.
- ^ Lutz, Mark (septiembre de 2009). Aprendiendo Python (4a ed.). O'Reilly Media . pag. 48. ISBN 978-0-596-15806-4.
- ^ Guelich, Gundavaram y Birznieks, Scott, Shishir y Gunther (29 de julio de 2000). Programación CGI con PERL (2ª ed.). O'Reilly Media . pag. 358 . ISBN 978-1-56592-419-2.
- ^ Lie Hetland, Magnus (4 de octubre de 2005). Python principiante: de principiante a profesional . Presione. pag. 21. ISBN 978-1-59059-519-0.
- ^ Schitka, John (24 de diciembre de 2002). Linux + Guía para la certificación de Linux . Tecnología del curso. pag. 353. ISBN 978-0-619-13004-6.
- ^ a b "execve (2) - página de manual de Linux" . Consultado el 21 de octubre de 2010 .
- ^ Corbet, Jonathan. "El caso del shebang de gran tamaño" . LWN.net .
- ^ "SRFI 22" .
- ^ https://stackoverflow.com/questions/45444823/python3-shebang-line-not-working-as-expected
- ^ "Las especificaciones de base de Open Group Issue 7" . 2008 . Consultado el 5 de abril de 2010 .
- ^ "pixelbeat.org: errores comunes de secuencias de comandos de shell" .
Es mucho mejor probar los scripts directamente en un shell compatible con POSIX si es posible. La opción `bash --posix` no es suficiente ya que todavía acepta algunos 'bashismos'
- ^ "Capítulo 2. Lenguaje de comandos de shell" , Especificaciones básicas de Open Group (IEEE Std 1003.1-2017) (Edición 7 ed.), IEEE, 2018 [2008],
si la primera línea de un archivo de comandos de shell comienza con los caracteres " #! ", los resultados no están especificados.
- ^ Autoconf , Free Software Foundation,
Macro: AC_SYS_INTERPRETER: Compruebe si el sistema admite scripts de inicio con una línea de la forma '#! / Bin / sh' para seleccionar el intérprete que se utilizará para el script.
- ^ "Comportamiento de / usr / bin / env" . Mail-index.netbsd.org. 9 de noviembre de 2008 . Consultado el 18 de noviembre de 2010 .
- ^ - Manual de comandos generales de FreeBSD
- ^ "invocación env" . GNU Coreutils . Consultado el 11 de febrero de 2020 .
- ^ "El retorno de carro hace que bash falle" . 8 de noviembre de 2013.
- ^ "GNU Autoconf Manual v2.57, Capítulo 10: Programación de Shell portátil" . Archivado desde el original el 18 de enero de 2008 . Consultado el 14 de mayo de 2020 .
- ^ "La magia #!, Detalles sobre el mecanismo shebang / hash-bang en varios sabores de Unix" . Consultado el 14 de mayo de 2020 .
- ^ "Preguntas frecuentes: UTF-8, UTF-16, UTF-32 y BOM: ¿Puede un flujo de datos UTF-8 contener el carácter de BOM (en formato UTF-8)? Si es así, puedo asumir los bytes UTF-8 restantes. están en orden big-endian? " . Consultado el 4 de enero de 2009 .
- ^ "Entrada de archivo de jerga para shebang" . Catb.org . Consultado el 16 de junio de 2010 .
- ^ Pared, Larry . "Perl no asimiló los scripts setuid que tenían un espacio en la primera línea entre el shebang y el nombre del intérprete" . USENET .
- ^ a b "CD-ROM de archivo CSRG" .
- ^ UNIX TIME-SHARING SYSTEM: UNIX PROGRAMMER'S MANUAL (PDF) , 2A (Séptima ed.), Enero de 1979
- ^ Gilles. "linux - ¿Por qué SUID está deshabilitado para scripts de shell pero no para binarios?" . Intercambio de pilas de seguridad de la información .
- ^ Richie, Dennis. "Dennis Ritchie y Hash-Bang" . Talisman.org . Consultado el 3 de diciembre de 2020 .
- ^ Rubini, Alessandro (31 de diciembre de 1997). "Jugando con formatos binarios" . Diario de Linux . Consultado el 1 de enero de 2015 .
enlaces externos
- Detalles sobre el mecanismo shebang en varios sabores de Unix
- #! - la verdad de Unix hasta donde yo la conozco (un enfoque más genérico)
- Artículo de shebang de FOLDOC