Чому б не використовувати бездоріжних шебангів?


24

Чи можливо мати шебанг, що замість того, щоб вказати шлях до перекладача, він має ім'я інтерпретатора і дозволяє оболонці знайти його через $ PATH?

Якщо ні, то чи є причина?


Відповіді:


20

Пошук PATH - це особливість стандартної бібліотеки C у просторі користувачів, як і загальні змінні середовища. Ядро не бачить змінних середовища, за винятком випадків, коли він передає середовище від абонента execveдо нового процесу.

Ядро не виконує жодної інтерпретації на шляху в execve(це стосується функцій обгортання, таких як execvpпошук PATH) або в шебангу (який більш-менш повторно направляє execveвиклик всередину). Тож вам потрібно прокласти абсолютний шлях у шебанг¹. Оригінальна реалізація притон була всього лише кілька рядків коду, і він не був значно розширений з тих пір.

У перших версіях Unix оболонка робила роботу по виклику себе, коли помічала, що ви викликаєте сценарій. Шебанг був доданий в ядро ​​з кількох причин (узагальнення обгрунтування Денніса Річі :

  • Абоненту не потрібно переживати, чи програма для виконання - це сценарій оболонки або власний бінарний файл.
  • Сам скрипт визначає, який інтерпретатор використовувати замість абонента.
  • Ядро використовує ім'я сценарію в журналах.

Шляхи без шляхів вимагатимуть або збільшення ядра для доступу до змінних оточуючих середовищ та обробки PATH, або для того, щоб ядро ​​виконало програму простору користувача, яка виконує пошук PATH. Перший метод вимагає додати ядро ​​непропорційно велику складність. Другий метод вже можливий із #!/usr/bin/envшебангом .

¹ Якщо ви покладете відносний шлях, він інтерпретується відносно поточного каталогу процесу (а не до каталогу, що містить сценарій), що навряд чи є корисним у шебанге.


2
Ні, ядро ​​не вимагає абсолютного шляху execveні в шебанг, хоча мало сенсу мати відносний шлях у шебангу.
Стефан Шазелас

3
Для всіх, кому цікаво, як "shebang повторно направляє виклик execve всередину": це насправді частина загального механізму роботи інтерпретаторів на виконуваних файлах, які їм потрібні. Динамічно пов'язані виконувані файли ELF "інтерпретуються" /lib64/ld-linux-x86-64.so.2(див. lddВихід). Linux робить його повністю загальним: binfmtпідтримка (починаючи з 2.1.43) дозволяє реєструвати пари інтерпретатора-шлях / магія-число або файл-розширення. Ви можете мати виклик PE32 .exe, wineколи ви запускаєте їх, виклику файлів класу Java та файлів jar javaтощо тощо
Пітер Кордес,

#! / usr / bin / env -S [shebang] був потрібний мені для роботи вузла, не знаючи його шляху (використовуючи nvm - який розміщує його в іншому місці, ніж я спочатку очікував).
TamusJRoyce

-S доступний лише з Coreutils 8.30. Дивіться сторінку gitlab.com/gnuwget/wget/commit/… .
Тім Руесен rockdaboot

19

Там відбувається більше, ніж зустрічає око. #!рядки інтерпретуються ядром Unix або Linux, #!це не аспект оболонок. Це означає, що PATHнасправді не існує того часу, коли ядро ​​вирішує, що потрібно виконати.

Найпоширеніший спосіб впоратися з невідомістю якого виконуваного файлу, або зателефонувати perlна портативний або подібний спосіб, - це використовувати #!/usr/bin/env perl. Ядро виконує /usr/bin/env, що успадковує PATHзмінну середовища. envзнаходить (у цьому прикладі) perlв PATHі використовує execve(2)системний виклик для отримання ядра для запуску perlвиконуваного файлу.


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

Перетворення на повний шлях здійснюється оболонкою (більш загальне: в просторі користувачів). Ядро очікує назви файла / шляху, до якого він може отримати доступ безпосередньо.

Якщо ви хочете, щоб система знайшла ваш виконуваний файл, переглянувши змінну PATH, ви можете переписати свій шебанг як #!/usr/bin/env EXEC.

Але також в цьому випадку пошук не ядро.


1
Перетворення на повний шлях здійснюється оболонкою Спасибі, хоча ... чи приклад повинен ілюструвати це? Як я бачу, оболонка просто працює strace(перетворена /usr/bin/straceв якийсь момент) з 2 аргументами.
Алоїс Магдал
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.