Mengapa tidak menggunakan shebang tanpa jalan?

Jawaban:

20

Pencarian PATH adalah fitur dari pustaka C standar di userspace, seperti variabel lingkungan pada umumnya. Kernel tidak melihat variabel lingkungan kecuali ketika melewati lingkungan dari pemanggil execveke proses baru.

Kernel tidak melakukan interpretasi apa pun pada path in execve(terserah fungsi wrapper seperti execvpuntuk melakukan pencarian PATH) atau dalam shebang (yang lebih kurang merutekan kembali execvepanggilan secara internal). Jadi Anda harus meletakkan jalur absolut di shebang¹. The pelaksanaan shebang asli hanya beberapa baris kode, dan belum secara signifikan diperluas sejak.

Dalam versi pertama Unix, shell melakukan pekerjaan memohon sendiri ketika Anda melihat Anda memohon sebuah skrip. Shebang ditambahkan dalam kernel karena beberapa alasan (meringkas alasan oleh Dennis Ritchie :

  • Penelepon tidak perlu khawatir apakah program yang akan dijalankan adalah skrip shell atau biner asli.
  • Script itu sendiri menentukan penerjemah apa yang akan digunakan, bukan penelepon.
  • Kernel menggunakan nama skrip dalam log.

Pathless shebang akan membutuhkan untuk menambah kernel untuk mengakses variabel dan proses lingkungan PATH, atau untuk meminta kernel mengeksekusi program userspace yang melakukan pencarian PATH. Metode pertama membutuhkan penambahan kompleksitas yang tidak proporsional ke kernel. Metode kedua sudah mungkin dengan #!/usr/bin/envshebang .

¹ Jika Anda meletakkan jalur relatif, itu ditafsirkan secara relatif ke direktori saat ini dari proses (bukan direktori yang berisi skrip), yang hampir tidak berguna di shebang.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
2
Tidak, kernel tidak memerlukan path absolut di execvedalam shebang walaupun tidak masuk akal untuk memiliki path relatif di shebang.
Stéphane Chazelas
3
Bagi siapa pun yang penasaran tentang bagaimana "shebang merutekan panggilan eksekutif ke dalam": Ini sebenarnya bagian dari mekanisme umum untuk menjalankan penerjemah pada executable yang membutuhkannya. Executable ELF yang terhubung secara dinamis "ditafsirkan" oleh /lib64/ld-linux-x86-64.so.2(lihat lddoutput). Linux menjadikannya sepenuhnya generik: binfmtdukungan (sejak 2.1.43) memungkinkan Anda mendaftar pasangan interpreter-path / magic-number-atau-file-extension. Anda dapat memiliki PE32 .exes Invoke wineketika Anda menjalankan mereka, kelas dan jar file Java memanggil java, dll dll
Peter Cordes
#! / usr / bin / env -S [shebang] diperlukan untuk saya menjalankan simpul tanpa mengetahui jalurnya (menggunakan nvm - yang menempatkannya di lokasi yang berbeda dari yang saya perkirakan).
TamusJRoyce
-S hanya tersedia sejak coreutils 8.30. Lihat gitlab.com/gnuwget/wget/commit/… .
Tim Ruehsen rockdaboot
19

Ada lebih banyak hal yang terjadi daripada yang terlihat. #!baris ditafsirkan oleh kernel Unix atau Linux, #!bukan merupakan aspek shell. Ini berarti PATHtidak ada pada saat kernel memutuskan apa yang akan dieksekusi.

Cara paling umum untuk berurusan dengan tidak mengetahui yang dapat dijalankan untuk dijalankan, atau untuk memanggil perldengan cara portabel atau serupa, adalah menggunakan #!/usr/bin/env perl. Kernel dieksekusi /usr/bin/env, yang mewarisi PATHvariabel lingkungan. envmenemukan (dalam contoh ini) perldi PATHdan menggunakan execve(2)system call untuk mendapatkan kernel untuk menjalankan perlexecutable.

Bruce Ediger
sumber
4
$ strace sleep 1
execve("/usr/bin/sleep", ["sleep", "1"], [/* 99 vars */]) = 0

Konversi ke path lengkap dilakukan oleh shell (lebih umum: di userspace). Kernel mengharapkan nama file / jalur yang dapat diakses langsung.

Jika Anda ingin sistem menemukan executable Anda dengan melihat melalui variabel PATH, Anda dapat menulis ulang shebang Anda sebagai #!/usr/bin/env EXEC.

Tetapi juga dalam hal ini bukan kernel yang melakukan pencarian.

Hauke ​​Laging
sumber
1
Konversi ke path lengkap dilakukan oleh shell Terima kasih, meskipun ... adalah contoh yang seharusnya menggambarkan itu? Seperti yang saya lihat, shell hanya berjalan strace(dikonversi ke /usr/bin/stracebeberapa titik) dengan 2 argumen.
Alois Mahdal