Standard powłoki POSIX mówi na tej stronie
http://pubs.opengroup.org/onlinepubs/9699919799/
o tym, jak powłoki używają PATH
do wyszukiwania plików wykonywalnych:
„Listę należy przeszukiwać od początku do końca, stosując nazwę pliku do każdego prefiksu, aż do znalezienia pliku wykonywalnego o określonej nazwie i odpowiednich uprawnieniach do wykonywania.”
Cóż, nie tak to wygląda w rzeczywistej implementacji POSIX:
man which
mówi:
"zwraca nazwy ścieżek plików (lub linków), które byłyby wykonane w bieżącym środowisku, gdyby ich argumenty zostały podane jako polecenia w ściśle zgodnej z POSIX powłoce. Robi to, przeszukując PATH w poszukiwaniu plików wykonywalnych pasujących do nazw argumenty. Nie podąża za dowiązaniami symbolicznymi. ”
OK, spójrzmy na tę sytuację:
$ pwd
/home/mark
$ echo $PATH
/home/mark/bin:
...
$ ls -l bin/foobar
lrwxrwxrwx 1 mark mark 18 Dec 12 22:51 bin/foobar -> /home/mark/foobar1
$ touch foobar1
$ which foobar
$ chmod a+x foobar1
$ which foobar
/home/mark/bin/foobar
OK, tutaj jest dowiązanie symboliczne PATH
z poprawną nazwą i jest zgłaszane przez program ls
jako wykonywalny.
which
wcale na to nie patrzy, ale interesuje go tylko to, na co wskazuje.
Że pomimo faktu, że oba man which
wyraźnie mówią, że nie podąża za dowiązaniami symbolicznymi (i rzeczywiście widzimy, że nie, ponieważ which foobar
nie drukuje foobar1
), a także, że cytowana powyżej dokumentacja powłoki POSIX nigdy nie wspomina o dowiązaniach symbolicznych w PATH
algorytmie.
Tak więc, which
czy istniejące powłoki są nieprawidłowe, czy też nie rozumiem dokumentacji?
WYJAŚNIĆ:
Znam i potrafię wyjaśnić istniejące zachowanie. Moje pytanie nie brzmi „jak to działa?”. To wiem.
Moje pytanie dotyczy dokumentacji: gdzie jest mój błąd w stosowaniu cytowanej przeze mnie dokumentacji. A może dokumentacja jest nieprawidłowa?
MOTYWACJA: Dlaczego mnie to obchodzi?
Jestem implementatorem. Różni realizatorzy mają różne wymagania. Dla mnie wymaganiem jest, aby słowo obecnego standardu POSIX MUSI BYĆ DOKŁADNIE WYKONANE (lub, dokładniej, najlepiej, jak może być, ponieważ sam standard jest nieco błędny). Jakby to było słowo Boże.
Teraz standardowe sformułowanie jest dość jasne - nie wymieniono następujących dowiązań symbolicznych, gdzie w wielu innych miejscach wspomniano, gdzie należy to zrobić. Więc w tym przypadku nie.
Ja jednak zawsze dokładnie sprawdzić, jak dash
i bash
zachowywać, żeby się upewnić. Oczywiście jest tu również mały problem, dash
mimo że jest rozliczany jako POSIX, ma wiele małych błędów zgodnych z POSIX. bash
, Jeszcze nie znalazłem żadnych błędów w POSIX, ale ... bash nie jest tak naprawdę POSIX, to o wiele więcej.
Więc masz to. Dlatego mnie to obchodzi.
źródło
$PATH
może zawierać dowiązania symboliczne. Spróbowaćwhich sh
.$PATH
nie ma żadnych dowiązań symbolicznych.lstat(2)
), ich przestrzeganie zwykle nie jest określone. Na przykład, opisopen(2)
tylko wzmiankuje dowiązania symboliczne, gdy mówi się o zachowaniuO_CREAT | O_EXCL
. Nie trzeba podawać, że plik docelowy zostanie otwarty.Odpowiedzi:
Uprawnienia do samego dowiązania symbolicznego są nieistotne. Nie możesz ich nawet zmienić, jeśli spróbujesz.
Liczy się uprawnienia do pliku bazowego.
W porządku jest, aby katalogi w PATH zawierały dowiązania symboliczne do plików wykonywalnych. W rzeczywistości jest prawdopodobne, że wiele plików wykonywalnych w zmiennej PATH to dowiązania symboliczne. Na przykład w systemach typu debian / ubuntu:
Dokumentacja
Od
man chmod
:Przykład
Powłoka ma test,
-x
aby ustalić, czy plik jest wykonywalny. Spróbujmy:Tak jak w
which
przypadku powłoki, powłoka nie uważa pliku wykonywalnego softlink, chyba że plik źródłowy jest wykonywalny.Jak to działa
W systemie Debian
which
jest skryptem powłoki. Odpowiednia sekcja kodu to:Jak widać, wykorzystuje on
-x
test do ustalenia, czy plik jest wykonywalny.POSIX określa
-x
test w następujący sposób:POSIX sprawdza więc, do czego rozwiązuje się nazwa ścieżki . Innymi słowy, akceptuje dowiązania symboliczne.
Funkcja wykonująca POSIX
Funkcja wykonująca POSIX podąża za dowiązaniami symbolicznymi. Specyfikacja POSIX jest długa, aby określić warunki błędu, które może zgłosić, jeśli dowiązania symboliczne są okrągłe lub zbyt głębokie, takie jak:
źródło
which
jest skryptem powłoki. Prawdopodobnie po prostu korzystam z-x
testu, który pokazałem. Według POSIX-x
sprawdza, czy plik „rozpoznaje” plik wykonywalny. Jeśli widzisz coś innego, gdzie szukasz?which
działa, czy to jest,-x
czy coś innego. Chciałbym wiedzieć, gdzie nie przestrzegam poprawnie cytowanej przeze mnie dokumentacji.exec
funkcji następuje dowiązania. Wydaje się to dość jasne, że pliki dowiązane symbolicznie mogą być plikami wykonywalnymi w systemie POSIX.man which
który mówi: „Nie kanonizuje nazw ścieżek”. To nie znaczy, że nie podąża za linkami. Oznacza to tylko, jak zauważyłeś, że nie „kanonizuje” nazw.W tym przypadku dowiązania symboliczne są śledzone w sposób transparentny, bez kanonizacji końcowej ścieżki. Innymi słowy,
which
nie dba o/home/mark/bin
to, czy jest dowiązaniem symbolicznym, czy nie. Ważne jest, czy plik/home/mark/bin/foobar
istnieje, czy nie. Nie musi ręcznie spłaszczać dowiązań symbolicznych na ścieżce - system operacyjny może to zrobić samodzielnie.I rzeczywiście, gdy
which
pyta o informacje o pliku/home/mark/bin/foobar
, system operacyjny zauważa,/home/mark/bin
że jest dowiązaniem symbolicznym, podąża za nim i z powodzeniem znajdujefoobar
w katalogu docelowym.Jest to zachowanie domyślne, chyba że program używa
open(…, O_NOFOLLOW)
lubfstatat(…, AT_SYMLINK_NOFOLLOW)
uzyskuje dostęp do pliku.[komentarze zostały scalone]
Chociaż można powiedzieć, że media shell to zrobić na zasadzie case-by-case, to nie jest to samo z syscalli jądra: wszystkie połączenia związane z plikami zrobić śledzić dowiązania domyślnie, chyba że podano flagę „nofollow”. (Nawet lstat podąża za dowiązaniami symbolicznymi we wszystkich komponentach ścieżki oprócz ostatniego.)
Gdy specyfikacja nie mówi wprost o tym, co zrobić z dowiązaniami symbolicznymi, oznacza to, że zostanie użyte zachowanie domyślne. Oznacza to, że powłoka podążająca za algorytmem ścieżki nie rozpoznaje dowiązań symbolicznych ręcznie, ani też wyraźnie nie rezygnuje z tego, aby system operacyjny to robił. (Po prostu łączy każdy składnik $ PATH z nazwą pliku wykonywalnego.)
Kiedy strona podręcznika what (1) mówi, że nie podąża za dowiązaniami symbolicznymi, może to oznaczać kilka rzeczy, ale wersja GNU coreutils stwierdza to w ten sposób:
Jest to znacznie węższy zakres - oznacza to tylko, że
which
nie będzie próbował ręcznie kanonizować wszystkich ścieżek, aby usunąć duplikaty, ale nie oznacza to, że narzędzie zrezygnuje z dowiązania symbolicznego stosowanego przez system operacyjny w ogóle. Na przykład, jeśli/bin
jest dowiązaniem symbolicznym/usr/bin
, uruchomieniewhich -a sh
zwróci zarówno/bin/sh
i/usr/bin/sh
.źródło
which
podręcznika GNU stwierdza inaczej: „Które uznają dwa równoważne katalogi za różne, gdy jeden z nich zawiera ścieżkę z dowiązaniem symbolicznym”.execve("/home/mark/bin/foobar", …)
, spowoduje to, że wszystkie dowiązania symboliczne będą śledzone.execve
argument, właściwie to w mojej implementacji jest toexecl()
samo. Jeśli uwzględnisz to w swojej odpowiedzi, zaakceptuję.Powłoka jest zgodna ze swoją dokumentacją, ponieważ przestrzega zasad rozpoznawania nazw ścieżek.
which
jest zgodny z jego dokumentacją. Obaj robią nieco inne rzeczy.Wynikiem
which
jest nazwa pliku i ścieżka łącza, a nie ścieżka do tego, na co wskazuje dowiązanie symboliczne. Jest to zapisane na stronie podręcznika.Po wykonaniu polecenia łącze jest „śledzone” zgodnie z rozdziałem 4.13 Rozpoznawanie nazw ścieżek w ten sam sposób . Odpowiednią klauzulą dotyczącą wykonania pliku jest:
źródło