shebang y camino

22

¿Por qué un shebang necesita un camino?

Incorrecto

#!ruby

Correcto

#!/usr/local/bin/ruby

#!/usr/bin/env ruby

El sistema operativo debe tener la información sobre la ruta de un comando registrado, y ¿por qué todavía espera que se le dé?

sawa
fuente

Respuestas:

22

Probablemente para mantener el núcleo más simple. No creo que el núcleo busque su ruta para encontrar un ejecutable. Eso es manejado por la biblioteca C. #!el procesamiento se realiza en el kernel, que no usa la biblioteca estándar de C.

Además, no creo que el núcleo tenga una noción de cuál es su camino. $PATHes una variable de entorno, y solo los procesos tienen un entorno. El núcleo no lo hace. Supongo que podría acceder al entorno del proceso que hizo el ejecutivo, pero no creo que nada en el núcleo acceda a variables de entorno como esa.

cjm
fuente
5

Puede obtener la PATHsemántica de búsqueda mediante env, por lo tanto:

#!/usr/bin/env ruby  

tiene la semántica que le gustaría

#!ruby

La razón por la que depender de PATHno se considera una buena práctica es que el script no puede hacer suposiciones sobre el contenido de la variable de entorno PATH, rompiendo el "modelo de dependencia secuencial" de los archivos binarios donde

  1. /bin contiene los ejecutables necesarios en el momento del arranque;
  2. /usr/bin contiene los otros ejecutables utilizados por la instalación del sistema operativo;
  3. /usr/local/bin contiene ejecutables instalados por el administrador del sistema que no forman parte del sistema operativo base.
  4. ~/bin contiene los propios ejecutables del usuario.

Cada nivel no debe asumir la existencia de archivos binarios más adelante en la secuencia, que son más "aplicación" pero pueden depender de los archivos binarios anteriores, que son más "fundamentales". Y la variable PATH tiende a ejecutarse de aplicativa a fundamental, que es la dirección opuesta a la dependencia natural anterior.

Para ilustrar el problema, pregúntese qué sucede si una secuencia de comandos ~/bininvoca una secuencia de comandos /usr/local/binque invoca a Ruby. ¿Debería ese script depender de la versión instalada del sistema operativo /usr/bin/rubyo de la copia personal en la que el usuario tenga ~/bin/ruby? PATHla búsqueda proporciona la semántica impredecible asociada con el último (tal vez ~/bin/rubyes un enlace simbólico roto), mientras que se abre camino en el camino hacia #!el primero.

Realmente no hay ningún otro "sistema operativo ... independiente de la plataforma ... información sobre la ruta de un comando registrado", por lo que lo más simple es insistir en que la ruta se proporcione en el #!.

Charles Stewart
fuente
0

Creo que es para que pueda especificar un intérprete alternativo si lo necesita o quiere. Por ejemplo:

#!/home/user/myrubyinterpreter

Más a menudo visto con scripts de shell:

#!/bin/bash
#!/bin/sh
#!/bin/dash
#!/bin/csh
Andrew Lambert
fuente
44
Pero, ¿por qué eso lo haría necesario? Puede ejecutar ruby ​​directamente con ruby, pero eso no le impide especificar /home/user/myrubyinterpretersi lo desea
Michael Mrozek
El punto de Michael es exactamente lo que estoy preguntando.
sawa
0

Del libro Classic Shell Scripting :

Los scripts de shell suelen comenzar con #! /bin/sh. Utilice la ruta de acceso a un shell compatible con POSIX si /bin/shno es compatible con POSIX. También hay algunas "trampas" de bajo nivel a tener en cuenta:

  • Debe conocer la ruta completa al intérprete que se ejecutará. Esto puede evitar la portabilidad entre proveedores, ya que diferentes proveedores colocan las cosas en diferentes lugares (por ejemplo, /bin/awkversus /usr/bin/awk).
Arturo Herrero
fuente
-2

Hay otras razones, pero desde una perspectiva de seguridad, nunca quisiera que un script haga suposiciones sobre la ruta correcta. ¿Qué pasa si está mal y ejecuta el intérprete o intérprete de comandos incorrecto? ¿Uno que haya sido insertado por un usuario malicioso? ¿O qué sucede si se basa en un shell particular y se bloqueará si se usa el shell incorrecto?

Los usuarios pueden perder el tiempo con su ruta y romper cosas; no confíen en el usuario :-) He realizado numerosos ataques que dependen de que el usuario haga lo incorrecto con su ruta, generalmente obteniendo las cosas en el orden incorrecto, para que pueda subvertir Una llamada de guión normal.

Sí, sé que si ha escrito el guión usted mismo, puede afirmar con razón que ha resuelto su propio camino, pero un intérprete no puede tomar esas decisiones.

Rory Alsop
fuente
Esta preocupación solo se aplica si el script se ejecuta con privilegios elevados. Y eso es poco común, porque shebang y setxid no juegan bien juntos, y hay mucho más de qué preocuparse que $PATH. . Sin privilegios elevados, ¿qué LD_PRELOADpasa si se usa? PD Voto rechazado porque dar una advertencia falsa sobre seguridad es perjudicial para la seguridad.
Gilles 'SO- deja de ser malvado'
Su punto sobre setxid es válido, sin embargo, es un vector de ataque perfectamente útil, así que definitivamente no es una advertencia falsa
Rory Alsop
1
¿Podría dar un ejemplo de un caso en el que PATHsea ​​un vector de ataque y no haya tantos otros vectores de ataque que se deba repensar todo el enfoque?
Gilles 'SO- deja de ser malvado'
@Gilles - +1 tiene un buen punto, definitivamente, ya que si esto está roto, probablemente hay otras formas que son igual de válidas, sin embargo, en términos de cosas rotas que puede solucionar, esta es fácil.
Rory Alsop