Czy cel dowiązania symbolicznego jest względny względem katalogu nadrzędnego miejsca docelowego, a jeśli tak, to dlaczego?

14

Mam następującą strukturę plików:

build/
client/
  –> index.js

A kiedy próbuję utworzyć symboliczne łącze o nazwie „klient” w katalogu kompilacji, które odnosi się do katalogu klienta w cwd, tak jak

// Fails
$ pwd
/home/user/
$ ln -s client build/client 
$ stat build/client/index.js
stat: build/client/index.js: stat: Too many levels of symbolic links

Otrzymuję błąd ELOOP wyświetlony powyżej. Kiedy zmieniam ścieżkę docelową na względną do ścieżki docelowej, wszystko jest dobrze:

// Works
$ pwd
/home/user/
$ ln -s ../client build/client 
$ stat build/client/index.js
stat: <outputs file stats>

Czy jest to zamierzone zachowanie i proszę wyjaśnić, dlaczego ...

jibsales
źródło
ma to prawdopodobnie związek z efektem polegającym na tym, że używając ../ użyj ścieżki bezwzględnej do zadeklarowania ścieżki zamiast ścieżki względnej. dobrą praktyką jest zawsze stosowanie absolutnej ścieżki
Kiwy
Zgadzam się z najlepszą praktyką, ponieważ zawsze stosowałem ścieżki bezwzględne zarówno dla celu, jak i celu. Jednak strony podręcznika stwierdzają, że ścieżki względne mogą być używane dla obu ...
jibsales,

Odpowiedzi:

13

Dla tego, który nie działa, jeśli spojrzymy na ls -lwynik, otrzymujemy:

[sparticvs@sparta test]$ ls -l build/
total 0
lrwxrwxrwx. 1 sparticvs sparticvs 6 Dec 17 16:08 client -> client

Teraz, aby zrozumieć, co się tutaj dzieje. Spójrzmy na polecenie, które wywołałeś:

ln -s client build/client

Według strony podręcznika istnieją dwa możliwe dopasowania dla tego formatu

SYNOPSIS
       ln [OPTION]... [-T] TARGET LINK_NAME   (1st form)
       ln [OPTION]... TARGET... DIRECTORY     (3rd form)

Będzie pasować w pierwszej formie (od pierwszej). Teraz „nazwa docelowa” lub clientw twoim przypadku mogą być (zgodnie z kompletną lninstrukcją) ciągami dowolnymi. Nie muszą teraz rozwiązywać żadnych problemów, ale mogą rozwiązać coś w przyszłości. To, co tworzysz za pomocą swojego wywołania, to „wiszące dowiązanie symboliczne”, a system nie powstrzymuje cię przed ich utworzeniem.

Teraz twoje drugie wywołanie ln -s ../client build/clientto tak zwane „względne dowiązanie symboliczne” (jak zauważyłeś we własnym poście). Istnieje drugi typ i jest to „absolutne dowiązanie symboliczne”, które można wywołać przez wykonanie ln -s /home/user/client build/client.

To nie jest błąd. Zgodnie z instrukcją stwierdza:

Podczas tworzenia względnego dowiązania symbolicznego w innym miejscu niż bieżący katalog, rozdzielczość dowiązania symbolicznego będzie inna niż rozdzielczość tego samego ciągu z bieżącego katalogu. Dlatego wielu użytkowników woli najpierw zmienić katalogi na lokalizację, w której zostanie utworzone względne dowiązanie symboliczne, aby dopełnienie tabulacji lub inna rozdzielczość pliku znalazły ten sam cel, co zostanie umieszczony w dowiązaniu symbolicznym.

-- od info coreutils 'ln invocation'

To powiedziawszy, MUSISZ użyć względnej lub bezwzględnej ścieżki do celu.

sparticvs
źródło
5

To jest rzeczywiście zamierzone zachowanie. Ze strony podręcznika ln(1):

Dowiązania symboliczne mogą zawierać dowolny tekst; jeśli zostanie później rozwiązany, odnośnik względny jest interpretowany w odniesieniu do jego katalogu nadrzędnego.

Jeśli chodzi o jego powód, wyobraź sobie, że dowiązanie symboliczne było interpretowane raczej w odniesieniu do jego źródła, a nie jego przeznaczenia. Później, gdy go rozwiążesz, będziesz musiał wiedzieć, jakie było twoje CWD podczas jego tworzenia, co jest nonsensowne, a co dopiero niemożliwe.

Co więcej, w ten sposób otrzymujesz zgrabną i zwartą metodę tworzenia szkieletowej struktury katalogów, którą możesz upuścić w dowolnym miejscu drzewa katalogów bez przerywania dowiązań symbolicznych.

Aby dać przykład, co mam na myśli, powiedzmy, że pracujesz nad projektem i masz skonfigurowaną całą strukturę katalogów w ten sposób:

$ ls -1 /home/you/project
thingummies/
widgets/
wizardry/

Załóżmy teraz, że chcesz utworzyć dowiązanie symboliczne do widgets/wewnątrz wizardry/. Masz dwie opcje:

$ ln -s /home/you/project/widgets /home/you/project/wizardry

lub

$ ln -s ../widgets /home/you/project/wizardry

Jeśli następnie spróbujesz przenieść się /home/you/projectgdziekolwiek indziej, dowiązanie symboliczne utworzone za pomocą pierwszego formularza zostanie zerwane, ponieważ szuka /home/you/project/widgets. Druga forma utrzyma funkcjonalność dowiązania symbolicznego, ponieważ szuka ../widgets względnego miejsca, w którym się znajduje, niezależnie od tego, gdzie to miejsce może być w drzewie katalogów.

Joseph R.
źródło