Чи можливо мати шебанг, що замість того, щоб вказати шлях до перекладача, він має ім'я інтерпретатора і дозволяє оболонці знайти його через $ PATH?
Якщо ні, то чи є причина?
Чи можливо мати шебанг, що замість того, щоб вказати шлях до перекладача, він має ім'я інтерпретатора і дозволяє оболонці знайти його через $ PATH?
Якщо ні, то чи є причина?
Відповіді:
Пошук PATH - це особливість стандартної бібліотеки C у просторі користувачів, як і загальні змінні середовища. Ядро не бачить змінних середовища, за винятком випадків, коли він передає середовище від абонента execve
до нового процесу.
Ядро не виконує жодної інтерпретації на шляху в execve
(це стосується функцій обгортання, таких як execvp
пошук PATH) або в шебангу (який більш-менш повторно направляє execve
виклик всередину). Тож вам потрібно прокласти абсолютний шлях у шебанг¹. Оригінальна реалізація притон була всього лише кілька рядків коду, і він не був значно розширений з тих пір.
У перших версіях Unix оболонка робила роботу по виклику себе, коли помічала, що ви викликаєте сценарій. Шебанг був доданий в ядро з кількох причин (узагальнення обгрунтування Денніса Річі :
Шляхи без шляхів вимагатимуть або збільшення ядра для доступу до змінних оточуючих середовищ та обробки PATH
, або для того, щоб ядро виконало програму простору користувача, яка виконує пошук PATH. Перший метод вимагає додати ядро непропорційно велику складність. Другий метод вже можливий із #!/usr/bin/env
шебангом .
¹ Якщо ви покладете відносний шлях, він інтерпретується відносно поточного каталогу процесу (а не до каталогу, що містить сценарій), що навряд чи є корисним у шебанге.
execve
ні в шебанг, хоча мало сенсу мати відносний шлях у шебангу.
/lib64/ld-linux-x86-64.so.2
(див. ldd
Вихід). Linux робить його повністю загальним: binfmt
підтримка (починаючи з 2.1.43) дозволяє реєструвати пари інтерпретатора-шлях / магія-число або файл-розширення. Ви можете мати виклик PE32 .exe
, wine
коли ви запускаєте їх, виклику файлів класу Java та файлів jar java
тощо тощо
Там відбувається більше, ніж зустрічає око. #!
рядки інтерпретуються ядром Unix або Linux, #!
це не аспект оболонок. Це означає, що PATH
насправді не існує того часу, коли ядро вирішує, що потрібно виконати.
Найпоширеніший спосіб впоратися з невідомістю якого виконуваного файлу, або зателефонувати perl
на портативний або подібний спосіб, - це використовувати #!/usr/bin/env perl
. Ядро виконує /usr/bin/env
, що успадковує PATH
змінну середовища. env
знаходить (у цьому прикладі) perl
в PATH
і використовує execve(2)
системний виклик для отримання ядра для запуску perl
виконуваного файлу.
$ strace sleep 1
execve("/usr/bin/sleep", ["sleep", "1"], [/* 99 vars */]) = 0
Перетворення на повний шлях здійснюється оболонкою (більш загальне: в просторі користувачів). Ядро очікує назви файла / шляху, до якого він може отримати доступ безпосередньо.
Якщо ви хочете, щоб система знайшла ваш виконуваний файл, переглянувши змінну PATH, ви можете переписати свій шебанг як #!/usr/bin/env EXEC
.
Але також в цьому випадку пошук не ядро.
strace
(перетворена /usr/bin/strace
в якийсь момент) з 2 аргументами.