Wiersz Shebang z poleceniem `#! / Usr / bin / env --argument` kończy się niepowodzeniem w systemie Linux

53

Mam prosty skrypt:

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

W moim systemie OSX działa dobrze:

osx% ./script.rb
hi

Jednak w moim Linux-ie generuje błąd

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

Jeśli uruchomię linię shebang ręcznie, działa dobrze

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

Ale mogę powtórzyć błąd, jeśli spakuję ruby --verbosejeden argument doenv

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

Myślę więc, że jest to problem z envinterpretacją resetowania linii shebang. Używam 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.

To wydaje się naprawdę dziwne. Czy jest to częsty problem z tą wersją env, czy może dzieje się tu coś jeszcze, czego nie wiem?

szaleństwo
źródło
4
istotnych?
rampion
To samo dotyczy Coreutils 8.17. Dziwne. Raportowanie do Fedory, ponieważ jest to wyraźnie sprzeczne z tym, co mówi instrukcja.
vonbrand,
@vonbrand Co powiedziała Fedora? „Nie obchodzi nas to”.
kot

Odpowiedzi:

44

Wygląda na to, że Linux (w przeciwieństwie do BSD) przekazuje tylko jeden argument do polecenia shebang (w tym przypadku env).

Zostało to szeroko omówione na StackOverflow .

szaleństwo
źródło
3
zobacz także tę stronę, aby zapoznać się z zachowaniem różnych Uniksów.
Stéphane Chazelas,
4
Niepowodzenie specyfikacji. Mój Boże.
Konrad Rudolph,
3
Jeśli przez „specyfikację zawiodę” masz na myśli, że wszystkie systemy uniksowe powinny zaakceptować więcej niż 1 argument, to w 100% się z tobą zgadzam :)
Alexander Mills
Nie tyle „linux”, co GNU.
będzie
5

Znalazłem to za pośrednictwem komentarza @rampion:

Zdarza się, że jądro przetwarza pierwsze dwa znaki pliku szukając # !. Jeśli zostaną znalezione, pomija wszystkie znaki spacji szukające znaku spacji i wyodrębnia ścieżkę interpretera, która musi być rzeczywistym plikiem wykonywalnym, a nie innym skryptem, chociaż Linux rozszerza to, aby umożliwić rekurencyjne przetwarzanie skryptu. Po znalezieniu tego przeskakuje do pierwszego znaku spacji, skąd przenosi się do następnego znaku nowej linii i przekazuje go jako pojedynczy argument do polecenia. Nie ma przetwarzania „powłoki” cudzysłowów ani innych znaków meta. Wszystko to jest bardzo proste i brutalne. Dlatego nie możesz się podobać z dostępnymi tam opcjami. Otrzymujesz dokładnie jeden argument zawierający spację, a „perl -w” jest tym, co jądro widzi tutaj i przekazuje.

Źródło: http://lists.gnu.org/archive/html/bug-sh-utils/2002-04/msg00020.html

Aalex Gabi
źródło