La línea Shebang con el comando `#! / Usr / bin / env --argument` falla en Linux

53

Tengo un script simple:

#!/usr/bin/env ruby --verbose
# script.rb
puts "hi"

En mi cuadro OSX, funciona bien:

osx% ./script.rb
hi

Sin embargo, en mi caja de Linux, arroja un error

linux% ./script.rb
/usr/bin/env: ruby --verbose: No such file or directory

Si ejecuto la línea shebang manualmente, funciona bien

linux% /usr/bin/env ruby --verbose ./script.rb
hi

Pero puedo replicar el error si empaco ruby --verboseen un solo argumento paraenv

linux% /usr/bin/env "ruby --verbose" ./script.rb
/usr/bin/env: ruby --verbose: No such file or directory

Así que creo que este es un problema con la forma de envinterpretar el restablecimiento de la línea shebang. Estoy usando GNU coreutils 8.4 env:

linux% /usr/bin/env --version
env (GNU coreutils) 8.4
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Richard Mlynarik and David MacKenzie.

Esto parece realmente extraño. ¿Es un problema común con esta versión envo hay algo más que no sé?

rampion
fuente
44
¿pertinente?
rampion
Lo mismo aquí con coreutils 8.17. Extraño. Informar a Fedora, ya que esto va explícitamente en contra de lo que dice el manual.
vonbrand
@vonbrand ¿Qué dijo Fedora? "No nos importa".
gato

Respuestas:

44

Parece que esto se debe a que Linux (a diferencia de BSD) solo pasa un único argumento al comando shebang (en este caso env).

Esto ha sido ampliamente discutido en StackOverflow .

rampion
fuente
3
vea también esta página para una revisión del comportamiento en diferentes Unices.
Stéphane Chazelas
44
La especificación falla. Dios mío.
Konrad Rudolph
3
Si por "falla de especificación" quiere decir que todos los sistemas Unix deberían aceptar más de 1 argumento, entonces estoy 100% de acuerdo con usted :)
Alexander Mills
No tanto 'linux' como GNU.
se
5

Encontré esto a través del comentario de @rampion:

Lo que sucede es que el núcleo procesa los dos primeros caracteres del archivo buscando # !. Si se encuentran, saltea todos los caracteres de espacio en busca de un carácter que no sea de espacio y extrae la ruta del intérprete, que debe ser un ejecutable real y no otro script, aunque Linux lo extiende para permitir el procesamiento recursivo del script. Después de descubrir que luego salta al primer carácter que no sea espacio, desde donde pasa al siguiente carácter de nueva línea y lo pasa como un argumento único al comando. No hay procesamiento 'shell' de citas u otros metacaracteres. Es todo muy simple y fuerza bruta. Por lo tanto, no puede obtener fantasía con opciones allí. Obtiene exactamente un argumento espacio en blanco incluido y 'perl -w' es lo que el núcleo ve aquí y pasa.

Fuente: http://lists.gnu.org/archive/html/bug-sh-utils/2002-04/msg00020.html

Aalex Gabi
fuente