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.
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).
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.
$ 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.
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.
Odpowiedzi:
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
execve
do nowego procesu.Jądro nie dokonuje żadnej interpretacji ścieżki w
execve
(zależy od funkcji otoki, takich jakexecvp
wyszukiwanie PATH) lub w shebang (który mniej więcej przekierowujeexecve
wewnę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 :
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/env
shebang .¹ 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.
źródło
execve
ani w shebang, chociaż nie ma sensu mieć ścieżki względnej w shebang./lib64/ld-linux-x86-64.so.2
(patrzldd
dane wyjściowe). Linux sprawia, że jest w pełni ogólny:binfmt
obsługa (od 2.1.43) pozwala rejestrować pary interpreter-ścieżka / magiczny numer lub rozszerzenie pliku. Możesz.exe
uruchomić PE32wine
po uruchomieniu, wywołać klasę Java i pliki jarjava
, itp. Itd.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, żePATH
tak 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ć
perl
w sposób przenośny lub podobny, jest użycie#!/usr/bin/env perl
. Jądro wykonuje się/usr/bin/env
, co dziedziczyPATH
zmienną środowiskową.env
znaleziska (w tym przykładzie)perl
wPATH
i wykorzystujeexecve(2)
wywołanie systemowe, aby jądra do uruchomieniaperl
pliku wykonywalnego.źródło
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.
źródło
strace
(/usr/bin/strace
w pewnym momencie została przekonwertowana ) z 2 argumentami.