¿Es posible tener un shebang que, en lugar de especificar una ruta a un intérprete, tenga el nombre del intérprete y permita que el shell lo encuentre a través de $ PATH?
La búsqueda de RUTA es una característica de la biblioteca C estándar en el espacio de usuario, al igual que las variables de entorno en general. El núcleo no ve las variables de entorno, excepto cuando pasa sobre un entorno desde el llamador execveal nuevo proceso.
El kernel no realiza ninguna interpretación en la ruta en execve(depende de las funciones de envoltura, como execvprealizar una búsqueda de RUTA) o en un shebang (que más o menos redirige la execvellamada internamente). Por lo tanto, debe poner la ruta absoluta en el shebang¹. La implementación original de shebang fue solo unas pocas líneas de código, y no se ha expandido significativamente desde entonces.
En las primeras versiones de Unix, el shell hizo el trabajo de invocar a sí mismo cuando notó que estaba invocando un script. Shebang fue agregado al núcleo por varias razones (resumiendo la justificación de Dennis Ritchie :
La persona que llama no tiene que preocuparse si un programa para ejecutar es un script de shell o un binario nativo.
El script en sí especifica qué intérprete usar, en lugar de la persona que llama.
El núcleo usa el nombre del script en los registros.
Los shebangs sin ruta requerirían aumentar el kernel para acceder a las variables de entorno y el proceso PATH, o hacer que el kernel ejecute un programa de espacio de usuario que realice la búsqueda PATH. El primer método requiere agregar una cantidad desproporcionada de complejidad al núcleo. El segundo método ya es posible con un #!/usr/bin/envshebang .
¹ Si coloca una ruta relativa, se interpreta relativamente en el directorio actual del proceso (no en el directorio que contiene la secuencia de comandos), lo cual no es útil en un shebang.
No, el núcleo no requiere una ruta absoluta execveni en el shebang, aunque tiene poco sentido tener una ruta relativa en un shebang.
Stéphane Chazelas
3
Para cualquiera que tenga curiosidad acerca de cómo "shebang redirige la llamada ejecutiva internamente": en realidad es parte de un mecanismo genérico para ejecutar intérpretes en ejecutables que los necesitan. Los ejecutables ELF vinculados dinámicamente son "interpretados" por /lib64/ld-linux-x86-64.so.2(ver lddsalida). Linux lo hace completamente genérico: el binfmtsoporte (desde 2.1.43) le permite registrar pares de ruta de intérprete / número mágico o extensión de archivo. Puede ejecutar la .exeinvocación de PE32 winecuando los ejecuta, invocar la clase Java y los archivos jar java, etc., etc.
Peter Cordes
#! / usr / bin / env -S [shebang] fue necesario para ejecutar el nodo sin conocer su ruta (usando nvm, que lo coloca en una ubicación diferente de la que originalmente esperaba).
Están sucediendo más de lo que parece. #!las líneas son interpretadas por el kernel de Unix o Linux, #!no es un aspecto de los shells. Esto significa que PATHrealmente no existe en el momento en que el núcleo decide qué ejecutar.
La forma más común de lidiar con no saber qué ejecutable ejecutar, o llamar perlde forma portátil o similar, es usar #!/usr/bin/env perl. Se ejecuta el núcleo /usr/bin/env, que hereda una PATHvariable de entorno. envhallazgos (en este ejemplo) perlen PATHy utiliza la execve(2)llamada al sistema para obtener el kernel para ejecutar el perlejecutable.
$ strace sleep 1
execve("/usr/bin/sleep",["sleep","1"],[/*99 vars */])=0
La conversión a la ruta completa la realiza el shell (más general: en el espacio de usuario). El kernel espera un nombre / ruta de archivo al que pueda acceder directamente.
Si desea que el sistema encuentre su ejecutable mirando a través de la variable PATH, puede reescribir su shebang como #!/usr/bin/env EXEC.
Pero también en este caso no es el núcleo quien hace la búsqueda.
La conversión a la ruta completa se realiza mediante el shell Gracias, aunque ... ¿se supone que el ejemplo ilustra eso? A mi modo de ver, el shell se está ejecutando strace(convertido /usr/bin/straceen algún momento) con 2 argumentos.
Respuestas:
La búsqueda de RUTA es una característica de la biblioteca C estándar en el espacio de usuario, al igual que las variables de entorno en general. El núcleo no ve las variables de entorno, excepto cuando pasa sobre un entorno desde el llamador
execve
al nuevo proceso.El kernel no realiza ninguna interpretación en la ruta en
execve
(depende de las funciones de envoltura, comoexecvp
realizar una búsqueda de RUTA) o en un shebang (que más o menos redirige laexecve
llamada internamente). Por lo tanto, debe poner la ruta absoluta en el shebang¹. La implementación original de shebang fue solo unas pocas líneas de código, y no se ha expandido significativamente desde entonces.En las primeras versiones de Unix, el shell hizo el trabajo de invocar a sí mismo cuando notó que estaba invocando un script. Shebang fue agregado al núcleo por varias razones (resumiendo la justificación de Dennis Ritchie :
Los shebangs sin ruta requerirían aumentar el kernel para acceder a las variables de entorno y el proceso
PATH
, o hacer que el kernel ejecute un programa de espacio de usuario que realice la búsqueda PATH. El primer método requiere agregar una cantidad desproporcionada de complejidad al núcleo. El segundo método ya es posible con un#!/usr/bin/env
shebang .¹ Si coloca una ruta relativa, se interpreta relativamente en el directorio actual del proceso (no en el directorio que contiene la secuencia de comandos), lo cual no es útil en un shebang.
fuente
execve
ni en el shebang, aunque tiene poco sentido tener una ruta relativa en un shebang./lib64/ld-linux-x86-64.so.2
(verldd
salida). Linux lo hace completamente genérico: elbinfmt
soporte (desde 2.1.43) le permite registrar pares de ruta de intérprete / número mágico o extensión de archivo. Puede ejecutar la.exe
invocación de PE32wine
cuando los ejecuta, invocar la clase Java y los archivos jarjava
, etc., etc.Están sucediendo más de lo que parece.
#!
las líneas son interpretadas por el kernel de Unix o Linux,#!
no es un aspecto de los shells. Esto significa quePATH
realmente no existe en el momento en que el núcleo decide qué ejecutar.La forma más común de lidiar con no saber qué ejecutable ejecutar, o llamar
perl
de forma portátil o similar, es usar#!/usr/bin/env perl
. Se ejecuta el núcleo/usr/bin/env
, que hereda unaPATH
variable de entorno.env
hallazgos (en este ejemplo)perl
enPATH
y utiliza laexecve(2)
llamada al sistema para obtener el kernel para ejecutar elperl
ejecutable.fuente
La conversión a la ruta completa la realiza el shell (más general: en el espacio de usuario). El kernel espera un nombre / ruta de archivo al que pueda acceder directamente.
Si desea que el sistema encuentre su ejecutable mirando a través de la variable PATH, puede reescribir su shebang como
#!/usr/bin/env EXEC
.Pero también en este caso no es el núcleo quien hace la búsqueda.
fuente
strace
(convertido/usr/bin/strace
en algún momento) con 2 argumentos.