¿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?
Si no, ¿hay alguna razón por la cual?
¿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?
Si no, ¿hay alguna razón por la cual?
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 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 :
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.
execveni en el shebang, aunque tiene poco sentido tener una ruta relativa en un shebang.
/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.
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.
strace(convertido /usr/bin/straceen algún momento) con 2 argumentos.