stringtranslate.com

Shebang (Unix)

En informática , un shebang es la secuencia de caracteres #!, que consta de los caracteres signo de número (también conocido como sostenido o almohadilla ) y signo de exclamación (también conocido como bang ), al comienzo de un script . También se le llama sostenido-exclamación , sha-bang , [1] [2] hashbang , [3] [4] libra-bang , [5] [6] o hash-pling . [7]

Cuando se utiliza un archivo de texto con un shebang como si fuera un ejecutable en un sistema operativo tipo Unix , el mecanismo de carga del programa analiza el resto de la línea inicial del archivo como una directiva de interpretación . El cargador ejecuta el programa intérprete especificado , pasándole 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 un script se nombra con la ruta path /to/script y comienza con la línea #!/bin/sh, entonces se le indica al cargador del programa que ejecute el programa /bin/sh , pasando path/to/script como primer argumento.

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 lenguajes que no usan el signo almohadilla para comenzar comentarios aún pueden ignorar la línea shebang en reconocimiento de su propósito. [9]

Sintaxis

La forma de una directiva de interpretación shebang es la siguiente: [8]

#! intérprete [ arg-opcional ]

donde interpreter es una ruta a un programa ejecutable. El espacio entre #! e interpreter es opcional. Puede haber cualquier cantidad de espacios o tabulaciones antes o después de interpreter . El argumento opcional incluirá cualquier espacio adicional hasta el final de la línea.

En Linux , el archivo especificado por el intérprete se puede ejecutar si tiene los derechos de ejecución y es uno de los siguientes:

En Linux y Minix , un intérprete también puede ser un script. Una cadena de shebangs y wrappers 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 shebang #!/bin/A optparamy el archivo /bin/C contiene el shebang #!/bin/B, entonces la ejecución del archivo /bin/C se resuelve en /bin/B /bin/C, que finalmente se resuelve en /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 un script. [10]

Ejemplos

Algunas líneas típicas del shebang:

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. [11] A continuación se encuentran más pautas de portabilidad.

Objetivo

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 anteponer el intérprete a los scripts en la línea de comandos.

Por ejemplo, considere un script que tenga la línea inicial #!/bin/sh -x. Se lo puede invocar simplemente proporcionando su ruta de archivo, como some/path/to/foo, [12] y algunos parámetros, como bary baz:

algún/camino/a/foo bar baz

En este caso /bin/shse invoca en su lugar, con los parámetros -x, some/path/to/foo, bar, y baz, como si el comando original hubiera sido

/bin/sh -x alguna/ruta/a/foo bar baz

La mayoría de los intérpretes ponen a disposición del script cualquier argumento adicional. Si /bin/shes un shell compatible con POSIX , entonces bary bazse presentan al script como la matriz de parámetros posicionales "$@"y, de forma individual, como parámetros "$1"y "$2"respectivamente.

Debido a que el # inicial es el carácter que se utiliza para introducir comentarios en el lenguaje de shell POSIX (y en los lenguajes que entienden muchos otros intérpretes), el intérprete ignora toda la línea shebang. Sin embargo, es decisión del intérprete ignorar la línea shebang, y no todos lo hacen; por lo tanto, un script que consta de las dos líneas siguientes simplemente muestra ambas líneas cuando se ejecuta:

#!/bin/gato¡Hola Mundo!

Fortalezas

En comparación con el uso de listas de asociación globales entre extensiones de archivos y aplicaciones de interpretación, el método de 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 de intérpretes, sin sobrecargar el espacio de nombres de extensión de 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 script en sí es responsable de especificar el intérprete a utilizar.

Portabilidad

Ubicación del programa

Los shebangs deben 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 común.

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 . [13] En muchos sistemas Linux , /bin/sh es un enlace duro o simbólico a /bin/bash , el shell Bourne Again (BASH). El uso de una sintaxis específica de bash mientras se mantiene un shebang que apunta a sh tampoco es portable. [14]

Por este motivo, a veces es necesario editar la línea shebang después de copiar un script de una computadora a otra, ya que la ruta que se codificó en el script puede no ser aplicable en una nueva máquina, dependiendo de la consistencia en la convención anterior de ubicación del intérprete. Por este motivo y debido a que POSIX no estandariza los nombres de ruta, POSIX no estandariza la característica. [15] La herramienta GNU Autoconf puede probar la compatibilidad del sistema con la macro AC_SYS_INTERPRETER. [16]

A menudo, el programa /usr/bin/env se puede utilizar para evitar esta limitación introduciendo un nivel de indirección . va seguido de /usr/bin/env , seguido del comando deseado sin la ruta completa, como en este ejemplo:#!

#!/usr/bin/envsh

Esto funciona principalmente porque la ruta /usr/bin/env se usa comúnmente para la utilidad env e invoca el primer sh que se encuentra en el $PATH del usuario , normalmente /bin/sh .

Este ejemplo en particular (que utiliza sh ) tiene una utilidad limitada: ni /bin/sh ni /usr/bin/env son universales, y hay una cantidad similar de dispositivos que carecen de cada uno de ellos. En términos más generales, el uso de #!/usr/bin/env para cualquier script aún presenta algunos problemas de portabilidad con OpenServer 5.0.6 y Unicos 9.0.2, que solo tienen /bin/env y no /usr/bin/env .

El uso de #!/usr/bin/env da como resultado una indirección en tiempo de ejecución , lo que tiene el potencial de degradar la seguridad del sistema; por esta razón, algunos comentaristas recomiendan no usarlo [17] en software empaquetado, reservándolo solo para "ejemplos educativos".

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; [18] por ejemplo, al ejecutar el script con la primera línea,

#!/usr/bin/env python3 -c

Todo el texto después del primer espacio se trata como un único argumento, es decir, python3 -cse pasará como un argumento a /usr/bin/env en lugar de dos. Cygwin también se comporta de esta manera.

Las invocaciones complejas de intérpretes son posibles mediante el uso de un contenedor adicional . FreeBSD 6.0 (2005) introdujo una opción -S en su env , ya que cambió el comportamiento de lectura de shebang a no división. Esta opción le dice a env que divida la cadena por sí mismo. [19] La utilidad GNU env desde coreutils 8.30 (2018) también incluye esta característica. [20] Aunque el uso de esta opción mitiga el problema de portabilidad en el extremo del núcleo con la división, agrega el requisito de que env admita 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, tal vez como resultado de ser editados en un sistema que utiliza 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 da como resultado un mensaje de error. [21]

Número mágico

El shebang es en realidad una instancia legible por humanos de un número mágico en el archivo ejecutable, siendo la cadena de bytes mágicos 0x23 0x21 , la codificación de dos caracteres en ASCII de #! . Este número mágico es detectado por la familia de funciones " exec ", que determinan 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 [22] que algunas versiones antiguas de Unix esperan que el shebang normal esté seguido de un espacio y una barra ( ), pero esto parece ser falso; [11] en cambio, tradicionalmente se han permitido los espacios en blanco después del shebang, y a veces se han documentado con un espacio, como se describe en el correo electrónico histórico de 1980 a continuación.#! /

Los caracteres shebang se representan con los mismos dos bytes en las codificaciones ASCII extendidas , incluyendo UTF-8 , que se usa comúnmente para scripts y otros archivos de texto en los 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 BOM ( 0xEF 0xBB 0xBF ) antes del shebang evitará que se ejecute el intérprete de scripts. Algunas autoridades recomiendan no usar la marca de orden de bytes en scripts POSIX (similares a Unix), [23] 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 esa codificación no tiene problemas de endianness ; solo sirve para identificar la codificación como UTF-8. [23]

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 en shebang es que proviene del shell predeterminado sh , generalmente invocado con shebang. [24] Este uso era común en diciembre de 1989, [25] y probablemente antes.

Historia

Dennis Ritchie introdujo esta característica entre las ediciones 7 y 8 en los Laboratorios Bell. También se añadió a las versiones BSD de la Investigación en Ciencias de la Computación de Berkeley (presente en 2.8BSD [26] y activada por defecto en 4.2BSD). Como la Edición 8 de Unix de los Laboratorios Bell de AT&T y las ediciones posteriores no se lanzaron al público, la primera aparición ampliamente conocida de esta característica fue en BSD.

La falta de una directiva de interpretación, pero el soporte para scripts de shell, es evidente en la documentación de la versión 7 de Unix en 1979, [27] que describe en cambio una función del shell Bourne donde los archivos con permiso de ejecución serían manejados especialmente por el shell, que (a veces dependiendo de los caracteres iniciales del script, como ":" o "#") generaría un subshell 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 los invocara desde dentro de un shell Bourne. Un intento de ejecutar directamente un archivo de este tipo a través de la llamada al sistema exec() del propio sistema operativo fallaría, impidiendo que los scripts se comportaran de manera uniforme como comandos normales del sistema.

Scripts de shell mejorados de la versión 8

En versiones posteriores de sistemas similares a Unix, esta inconsistencia se eliminó. Dennis Ritchie introdujo el soporte del núcleo para directivas de intérprete en enero de 1980, para la versión 8 de Unix , con la siguiente descripción: [26]

De uucp jueves 10 de enero 01:37:58 1980>Desde dmr jue 10 ene 04:25:49 1980 remoto de investigaciónSe ha cambiado el sistema de manera que si se está ejecutando un archivocomienza con los caracteres mágicos #!, el resto de la línea se entiendeser el nombre de un intérprete para el archivo ejecutado.Anteriormente (y de hecho todavía) la concha hacía gran parte de este trabajo;Se ejecutó automáticamente en un archivo de texto con modo ejecutable.cuando el nombre del archivo de texto se escribió como comando.Al poner la instalación en el sistema se obtiene lo siguientebeneficios.1) Hace que los scripts de shell se parezcan más a archivos ejecutables reales,porque pueden ser objeto de 'ejecutivo'.2) Si haces un 'ps' mientras se ejecuta dicho comando, es realEl nombre aparece en lugar de 'sh'.De igual forma la contabilidad se realiza sobre la base del nombre real.3) Los scripts de shell pueden tener un ID de usuario establecido . [a]4) Es más sencillo tener shells alternativos disponibles;Por ejemplo, si te gusta la Berkeley CSH, no hay duda al respecto.¿Qué shell debe interpretar un archivo?5) Permitirá que otros intérpretes se integren más fácilmente.Para aprovechar esta maravillosa oportunidad,poner #! /bin/sh en el margen izquierdo de la primera línea de sus scripts de shell.Los espacios en blanco después de ! son aceptables. Utilice una ruta completa (no se realiza ninguna búsqueda).Por el momento, toda la línea está restringida a 16 caracteres, peroEste límite se aumentará.

Función de script de shell sin nombre

Sin embargo, el creador de la función no le dio un nombre: [29]

De:  "Ritchie,  Dennis  M  (Dennis)**  CTR  **"  <dmr@[redacted]> Para:  <[redacted]@ talisman.org > Fecha: jue, 19 nov 2009 18:37:37 -0600 Asunto: RE: ¿Cómo llamas a tu línea #!<algo> ?          No recuerdo que alguna vez le diéramos un nombre propio.Fue bastante tarde cuando entró, creo que yo...Tuve la idea de alguien en una de las conferencias de UCB.en Berkeley Unix; puede que haya sido uno de los primeros enEn realidad lo instalo, pero fue una idea que tuve.De 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 ningún apodo en particular.para la construcción.

El soporte del kernel para directivas de intérprete se extendió a otras versiones de Unix, y una implementación moderna se puede ver en el código fuente del kernel de Linux en fs/binfmt_script.c . [30]

Este mecanismo permite que los scripts se utilicen en prácticamente cualquier contexto en el que puedan estar los programas compilados normales, incluso como programas de sistema completos e incluso como intérpretes de otros scripts. Sin embargo, como advertencia, algunas versiones tempranas del soporte del núcleo limitaban la longitud de la directiva de intérprete a aproximadamente 32 caracteres (solo 16 en su primera implementación), no lograban separar 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 se restrinja o deshabilite por motivos de seguridad (por ejemplo, la compatibilidad con set-user-id se ha deshabilitado para scripts en muchos sistemas).

Tenga en cuenta que, incluso en sistemas con soporte completo del núcleo para el número mágico #!, algunos scripts que carecen de directivas de interpretación (aunque por lo general aún requieren permiso de ejecución) aún se pueden ejecutar en virtud del manejo de scripts heredado del shell Bourne, aún presente en muchos de sus descendientes modernos. Los scripts son luego interpretados por el shell predeterminado del usuario.

Véase también

Notas

  1. ^ La función setuid está deshabilitada en la mayoría de los sistemas operativos modernos luego de darse cuenta de que una condición de carrera puede aprovecharse para cambiar el script mientras se procesa. [28]

Referencias

  1. ^ "Guía avanzada de scripts en 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 .
  2. ^ Cooper, Mendel (5 de noviembre de 2010). Guía avanzada de scripts de Bash 5.3, volumen 1. lulu.com. p. 5. ISBN 978-1-4357-5218-4.
  3. ^ MacDonald, Matthew (2011). HTML5: El manual que faltaba. Sebastopol, California: O'Reilly Media . pág. 373. ISBN 978-1-4493-0239-9.
  4. ^ Lutz, Mark (septiembre de 2009). Learning Python (4.ª ed.). O'Reilly Media . pág. 48. ISBN 978-0-596-15806-4.
  5. ^ Guelich, Gundavaram y Birznieks, Scott, Shishir y Gunther (29 de julio de 2000). Programación CGI con PERL (2.ª ed.). O'Reilly Media . p. 358. ISBN 978-1-56592-419-2.{{cite book}}: CS1 maint: varios nombres: lista de autores ( enlace )
  6. ^ Lie Hetland, Magnus (4 de octubre de 2005). Principiantes en Python: de principiante a profesional. Presione. pag. 21.ISBN 978-1-59059-519-0.
  7. ^ Schitka, John (24 de diciembre de 2002). Guía Linux+ para la certificación en Linux. Tecnología del curso. pág. 353. ISBN 978-0-619-13004-6.
  8. ^ ab "execve(2) - Página del manual de Linux" . Consultado el 21 de octubre de 2010 .
  9. ^ "SRI 22".
  10. ^ "Python - La línea shebang de Python3 no funciona como se esperaba".
  11. ^ ab Maschek, Sven (30 de diciembre de 2010). "La magia del #!, detalles sobre el mecanismo shebang/hash-bang: ¿Es necesario dejar un espacio en blanco después del #!?". www.in-ulm.de . Consultado el 18 de enero de 2024 .
  12. ^ si lo permiten los bits de permiso de ejecución del archivo
  13. ^ "Especificaciones básicas de The Open Group, número 7". 2008. Consultado el 5 de abril de 2010 .
  14. ^ "pixelbeat.org: errores comunes en los scripts 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 aún acepta algunos 'bashismos'
  15. ^ "Capítulo 2. Lenguaje de comandos de shell", Especificaciones básicas de The Open Group (IEEE Std 1003.1-2017) (edición número 7), IEEE, 2018 [2008], Si la primera línea de un archivo de comandos de shell comienza con los caracteres "#!", los resultados no se especifican.
  16. ^ Autoconf, Free Software Foundation, Macro: AC_SYS_INTERPRETER: Comprueba si el sistema admite el inicio de scripts con una línea del formato '#!/bin/sh' para seleccionar el intérprete que se utilizará para el script.
  17. ^ "¿Qué pasa con #!/usr/bin/env bash?" . Consultado el 6 de marzo de 2024 .
  18. ^ "Comportamiento de/usr/bin/env". Mail-index.netbsd.org. 9 de noviembre de 2008. Consultado el 18 de noviembre de 2010 .
  19. ^ env(1)  –  Manual de comandos generales de FreeBSD
  20. ^ "invocación de entorno". GNU Coreutils . Consultado el 11 de febrero de 2020 .
  21. ^ "El retorno de carro hace que bash falle". 8 de noviembre de 2013.
  22. ^ "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 .
  23. ^ ab "Preguntas frecuentes sobre UTF-8, UTF-16, UTF-32 y BOM: ¿Puede un flujo de datos UTF-8 contener el carácter BOM (en formato UTF-8)? Si es así, ¿puedo asumir que los bytes UTF-8 restantes están en orden big-endian?". Unicode . Consultado el 10 de noviembre de 2023 .
  24. ^ "Entrada de archivo de jerga para shebang". Catb.org . Consultado el 16 de junio de 2010 .
  25. ^ Wall, Larry . "Perl no entendía los scripts setuid que tenían un espacio en la primera línea entre el shebang y el nombre del intérprete". USENET .
  26. ^ ab "CD-ROM de archivo CSRG".
  27. ^ SISTEMA DE TIEMPO COMPARTIDO UNIX: MANUAL DEL PROGRAMADOR UNIX (PDF) , vol. 2A (séptima edición), enero de 1979
  28. ^ Gilles. "Linux: ¿Por qué SUID está deshabilitado para los scripts de shell pero no para los binarios?". Stack Exchange sobre seguridad de la información .
  29. ^ Richie, Dennis. "Dennis Ritchie y Hash-Bang". Talisman.org . Consultado el 3 de diciembre de 2020 .
  30. ^ Rubini, Alessandro (31 de diciembre de 1997). "Jugando con formatos binarios". Linux Journal . Consultado el 1 de enero de 2015 .

Enlaces externos