Baris Shebang dengan perintah `#! / Usr / bin / env --argument` gagal di Linux

53

Saya punya skrip sederhana:

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

Di kotak OSX saya, itu berjalan dengan baik:

osx% ./script.rb
hi

Namun, pada kotak linux saya, ada kesalahan

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

Jika saya menjalankan garis shebang secara manual, itu berfungsi dengan baik

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

Tapi saya bisa meniru kesalahan jika saya masukkan ruby --verboseke argumen tunggalenv

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

Jadi saya pikir ini adalah masalah dengan bagaimana envmenafsirkan reset garis shebang. Saya menggunakan 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.

Ini sepertinya sangat aneh. Apakah ini masalah umum dengan versi ini env, atau ada hal lain yang terjadi di sini yang tidak saya ketahui?

rampion
sumber
4
relevan?
rampion
Sama di sini dengan coreutils 8.17. Aneh. Melaporkan ke Fedora, karena ini bertentangan dengan apa yang dikatakan manual.
vonbrand
@vonbrand Apa yang dikatakan Fedora? "Kami tidak peduli."
kucing

Jawaban:

44

Sepertinya ini karena Linux (tidak seperti BSD) hanya meneruskan satu argumen ke perintah shebang (dalam hal ini env).

Ini telah banyak dibahas di StackOverflow .

rampion
sumber
3
lihat juga halaman ini untuk ulasan tentang perilaku pada berbagai Unix.
Stéphane Chazelas
4
Spesifikasi gagal. Tuhanku.
Konrad Rudolph
3
Jika dengan "spesifikasi gagal" maksud Anda semua sistem Unix harus menerima lebih dari 1 argumen, maka saya 100% setuju dengan Anda :)
Alexander Mills
Tidak terlalu banyak 'linux' seperti GNU.
akan
5

Menemukan ini melalui komentar @rampion:

Yang terjadi adalah bahwa kernel memproses dua karakter pertama dari file tersebut mencari # !. Jika itu ditemukan maka ia akan melompati semua karakter spasi mencari karakter non-spasi dan mengekstrak jalur penerjemah yang harus menjadi executable nyata dan bukan skrip lain, meskipun linux memperluasnya untuk memungkinkan pemrosesan skrip rekursif. Setelah menemukan itu maka ia melompat ke karakter non-spasi pertama di mana dibutuhkan dari sana ke karakter baris baru berikutnya dan meneruskannya sebagai argumen tunggal ke perintah. Tidak ada pemrosesan 'shell' dari tanda kutip atau karakter meta lainnya. Itu semua sangat sederhana dan kekerasan. Karenanya, Anda tidak dapat menyukai opsi di sana. Anda mendapatkan persis satu argumen yang termasuk dalam spasi putih dan 'perl -w' adalah apa yang dilihat kernel dan diteruskan.

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

Aalex Gabi
sumber