Чи можливо мати шебанг, що замість того, щоб вказати шлях до перекладача, він має ім'я інтерпретатора і дозволяє оболонці знайти його через $ 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 аргументами.