shebang i ścieżka

22

Dlaczego shebang potrzebuje ścieżki?

Źle

#!ruby

Poprawny

#!/usr/local/bin/ruby

#!/usr/bin/env ruby

System operacyjny powinien mieć informacje dotyczące ścieżki zarejestrowanego polecenia i dlaczego nadal oczekuje na jego podanie?

sawa
źródło

Odpowiedzi:

22

Prawdopodobnie w celu uproszczenia jądra. Nie sądzę, aby jądro kiedykolwiek przeszukiwało twoją ścieżkę w celu znalezienia pliku wykonywalnego. Jest to obsługiwane przez bibliotekę C. #!przetwarzanie odbywa się w jądrze, które nie korzysta ze standardowej biblioteki C.

Nie sądzę też, aby jądro miało pojęcie o twojej ścieżce. $PATHjest zmienną środowiskową i tylko procesy mają środowisko. Jądro nie. Przypuszczam, że może on uzyskać dostęp do środowiska procesu, który wykonał exec, ale nie sądzę, aby cokolwiek w jądrze kiedykolwiek uzyskiwało dostęp do takich zmiennych środowiskowych.

cjm
źródło
5

Możesz uzyskać PATH-semantykę wyszukiwania env, więc:

#!/usr/bin/env ruby  

ma semantykę, z której chcesz

#!ruby

Powodem, dla którego zależność PATHnie jest uważana za dobrą praktykę, jest to, że skrypt nie może przyjmować żadnych założeń dotyczących zawartości zmiennej środowiskowej PATH, niszcząc „sekwencyjny model zależności” plików binarnych, w których

  1. /bin zawiera pliki wykonywalne potrzebne podczas rozruchu;
  2. /usr/bin zawiera inne pliki wykonywalne używane podczas instalacji systemu operacyjnego;
  3. /usr/local/bin zawiera pliki wykonywalne zainstalowane przez administratora systemu, które nie są częścią podstawowego systemu operacyjnego.
  4. ~/bin zawiera własne pliki wykonywalne użytkownika.

Każdy poziom nie powinien zakładać istnienia plików binarnych w dalszej kolejności, które są bardziej „aplikacjami”, ale mogą polegać na plikach binarnych, które są bardziej „fundamentalne”. Zmienna PATH ma tendencję do działania od aplikacji do fundamentu, co jest odwrotnym kierunkiem do naturalnej zależności powyżej.

Aby zilustrować problem, zadaj sobie pytanie, co się stanie, jeśli skrypt ~/binwywołuje skrypt, /usr/local/binktóry wywołuje Ruby? Czy ten skrypt powinien zależeć od wersji zainstalowanej systemu operacyjnego /usr/bin/ruby, czy od osobistej kopii, w której użytkownik ma ten plik ~/bin/ruby? PATHwyszukiwanie daje nieprzewidywalną semantykę związaną z tym drugim (być może ~/bin/rubyjest zerwanym łączem symbolicznym), a pieczenie na ścieżce #!daje to pierwsze.

Tak naprawdę nie ma innego niezależnego od platformy „systemu operacyjnego ... informacji dotyczących ścieżki zarejestrowanego polecenia”, więc najprościej jest nalegać na podanie ścieżki w #!.

Charles Stewart
źródło
0

Wierzę, że tak, więc możesz określić alternatywnego tłumacza, jeśli potrzebujesz lub chcesz. Na przykład:

#!/home/user/myrubyinterpreter

Częściej spotykane ze skryptami powłoki:

#!/bin/bash
#!/bin/sh
#!/bin/dash
#!/bin/csh
Andrew Lambert
źródło
4
Ale dlaczego miałoby to powodować? Możesz uruchomić ruby ​​bezpośrednio ruby, ale to nie powstrzymuje cię przed określeniem, /home/user/myrubyinterpreterczy chcesz
Michael Mrozek
Pytanie Michaela jest dokładnie tym, o co pytam.
sawa
0

Z książki Classic Shell Scripting :

Skrypty powłoki zwykle zaczynają się od #! /bin/sh. Użyj ścieżki do powłoki zgodnej z POSIX, jeśli nie jesteś /bin/shzgodny z POSIX. Istnieją również „gotchas” niskiego poziomu, na które należy uważać:

  • Musisz znać pełną nazwę ścieżki do tłumacza, który chcesz uruchomić. Może to zapobiec przenośności między dostawcami, ponieważ różni dostawcy umieszczają rzeczy w różnych miejscach (np. /bin/awkKontra /usr/bin/awk).
Arturo Herrero
źródło
-2

Są inne powody, ale z punktu widzenia bezpieczeństwa nigdy nie chciałbym, aby skrypt przyjmował założenia dotyczące właściwej ścieżki. Co jeśli jest źle i uruchamia niewłaściwą powłokę lub interpretera? Ten, który został wstawiony przez złośliwego użytkownika? A co, jeśli opiera się na konkretnej powłoce i ulegnie awarii, jeśli zostanie użyta niewłaściwa powłoka?

Użytkownicy mogą zepsuć swoją ścieżkę i popsuć różne rzeczy - nie ufaj użytkownikowi :-) Przeprowadziłem wiele ataków, które polegają na tym, że użytkownik robi coś złego na swojej ścieżce - zwykle robi to w złej kolejności - więc mogę obalić normalne wywołanie skryptu.

Tak, wiem, że jeśli sam napisałeś skrypt, możesz słusznie twierdzić, że wytyczyłeś własną ścieżkę, ale tłumacz nie może podejmować tych decyzji.

Rory Alsop
źródło
Dotyczy to tylko sytuacji, gdy skrypt działa z podwyższonymi uprawnieniami. I to jest rzadkie, ponieważ shebang i setxid nie grają dobrze razem, a jest o wiele więcej powodów do zmartwień $PATH. . Bez podwyższonych uprawnień co się stanie, jeśli LD_PRELOADzostanie użyty? PS Przegłosowano, ponieważ fałszywe ostrzeżenie o bezpieczeństwie jest szkodliwe dla bezpieczeństwa.
Gilles „SO- przestań być zły”
Twoja uwaga na temat setxid jest poprawna, jednak jest to całkowicie przydatny wektor ataku, więc zdecydowanie nie jest to fałszywe ostrzeżenie
Rory Alsop
1
Czy możesz podać przykład przypadku, w którym PATHwektor ataku jest niewystarczający, i że nie ma tak wielu wektorów ataku, że należy ponownie przemyśleć całe podejście?
Gilles 'SO- przestań być zły'
@Gilles - +1 masz dobrą rację, zdecydowanie, jakby to było zepsute, prawdopodobnie istnieją inne sposoby, które są równie ważne, jednak pod względem zepsutych rzeczy, które możesz naprawić, jest to łatwe.
Rory Alsop,