Dlaczego nie zastosować bezpardonowych shebangów?


Odpowiedzi:


20

Wyszukiwanie PATH jest cechą standardowej biblioteki C w przestrzeni użytkownika, podobnie jak ogólnie zmienne środowiskowe. Jądro nie widzi zmiennych środowiskowych, z wyjątkiem sytuacji, gdy przechodzi ono przez środowisko wywołujące execvedo nowego procesu.

Jądro nie dokonuje żadnej interpretacji ścieżki w execve(zależy od funkcji otoki, takich jak execvpwyszukiwanie PATH) lub w shebang (który mniej więcej przekierowuje execvewewnętrznie wywołanie). Musisz więc umieścić absolutną ścieżkę w shebang¹. Oryginalna realizacja shebang było tylko kilka linii kodu, a nie został znacząco rozszerzony od.

W pierwszych wersjach Uniksa powłoka wykonała zadanie wywołania się, gdy zauważyła, że ​​wywołujesz skrypt. Shebang został dodany do jądra z kilku powodów (podsumowując uzasadnienie Dennisa Ritchiego :

  • Program wywołujący nie musi się martwić, czy program do wykonania jest skryptem powłoki, czy rodzimym plikiem binarnym.
  • Sam skrypt określa, jakiego interpretera użyć, zamiast wywołującego.
  • Jądro używa nazwy skryptu w logach.

Bezprzestrzenne shebangs wymagałyby albo rozszerzenia jądra, aby uzyskać dostęp do zmiennych środowiskowych i procesu PATH, albo też aby jądro wykonało program przestrzeni użytkownika, który wykonuje wyszukiwanie PATH. Pierwsza metoda wymaga dodania nieproporcjonalnej złożoności do jądra. Druga metoda jest już możliwa z #!/usr/bin/envshebang .

¹ Jeśli umieścisz ścieżkę względną, zostanie ona zinterpretowana w stosunku do bieżącego katalogu procesu (nie katalogu zawierającego skrypt), co jest mało przydatne w shebang.


2
Nie, jądro nie wymaga bezwzględnej ścieżki w execveani w shebang, chociaż nie ma sensu mieć ścieżki względnej w shebang.
Stéphane Chazelas

3
Dla każdego, kto jest ciekawy, jak „shebang wewnętrznie przekierowuje wywołanie execute”: W rzeczywistości jest to część ogólnego mechanizmu uruchamiania interpreterów na plikach wykonywalnych, które ich potrzebują. Dynamicznie połączone pliki wykonywalne ELF są „interpretowane” przez /lib64/ld-linux-x86-64.so.2(patrz ldddane wyjściowe). Linux sprawia, że ​​jest w pełni ogólny: binfmtobsługa (od 2.1.43) pozwala rejestrować pary interpreter-ścieżka / magiczny numer lub rozszerzenie pliku. Możesz .exeuruchomić PE32 winepo uruchomieniu, wywołać klasę Java i pliki jar java, itp. Itd.
Peter Cordes

#! / usr / bin / env -S [shebang] był wymagany dla mnie działającego węzła bez znajomości jego ścieżki (używając nvm - co umieszcza go w innym miejscu niż pierwotnie oczekiwałem).
TamusJRoyce

-S jest dostępna tylko od Coreutils 8.30. Zobacz gitlab.com/gnuwget/wget/commit/… .
Tim Ruehsen rockdaboot

19

Dzieje się więcej niż na pierwszy rzut oka. #!linie są interpretowane przez jądro Unixa lub Linuksa, #!nie jest to aspekt powłoki. Oznacza to, że PATHtak naprawdę nie istnieje w chwili, gdy jądro decyduje, co wykonać.

Najczęstszym sposobem radzenia sobie z nieświadomością, który plik wykonywalny uruchomić, lub aby zadzwonić perlw sposób przenośny lub podobny, jest użycie #!/usr/bin/env perl. Jądro wykonuje się /usr/bin/env, co dziedziczy PATHzmienną środowiskową. envznaleziska (w tym przykładzie) perlw PATHi wykorzystuje execve(2)wywołanie systemowe, aby jądra do uruchomienia perlpliku wykonywalnego.


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

Konwersja do pełnej ścieżki jest wykonywana przez powłokę (bardziej ogólnie: w przestrzeni użytkownika). Jądro oczekuje nazwy pliku / ścieżki, do której może uzyskać bezpośredni dostęp.

Jeśli chcesz, aby system znalazł plik wykonywalny, przeglądając zmienną PATH, możesz przepisać swój shebang jako #!/usr/bin/env EXEC.

Ale także w tym przypadku wyszukiwanie nie odbywa się przez jądro.


1
Konwersja do pełnej ścieżki jest wykonywana przez powłokę Dzięki, chociaż ... czy przykład ma to zilustrować? Jak widzę, powłoka właśnie działa strace( /usr/bin/stracew pewnym momencie została przekonwertowana ) z 2 argumentami.
Alois Mahdal
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.