Является ли цель символической ссылки относительно родительского каталога назначения и если да, то почему?

14

У меня есть следующая структура файла:

build/
client/
  –> index.js

И когда я пытаюсь создать символическую ссылку с именем "client" внутри каталога сборки, которая ссылается на каталог клиента в cwd, примерно так

// 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

Я получаю сообщение об ошибке ELOOP, показанное выше. Когда я изменяю целевой путь на относительный путь, все хорошо:

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

Это предполагаемое поведение, и, пожалуйста, объясните, почему ...

jibsales
источник
вероятно, это как-то связано с тем, что при использовании ../ используется абсолютный путь для объявления пути вместо относительного пути. хорошая практика - всегда использовать абсолютный путь
Kiwy
Я согласен с лучшей практикой, так как я всегда использовал абсолютные пути как для цели, так и для пункта назначения. Тем не менее, на страницах
руководства говорится,

Ответы:

13

Для того, кто не работает, если мы посмотрим на ls -lрезультат, мы получим следующее:

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

Теперь, чтобы понять, что здесь происходит. Давайте посмотрим на команду, которую вы вызвали:

ln -s client build/client

Согласно Man Page, есть два возможных совпадения для этого формата

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

Он будет совпадать с первой формой (начиная с первой). Теперь «целевое имя» или, clientв вашем случае, может быть (согласно полному lnруководству) произвольной строкой. Им не нужно ничего решать прямо сейчас, но они могут разрешить что-то в будущем. То, что вы создаете с помощью своего вызова, является «висячей символической ссылкой», и система не удерживает вас от их создания.

Теперь ваш второй вызов ln -s ../client build/client- это то, что называется «относительная символическая ссылка» (как вы отметили в своем посте). Существует второй тип, и это «абсолютная символическая ссылка», которая будет вызываться при выполнении ln -s /home/user/client build/client.

Это не ошибка. Согласно инструкции в нем говорится:

При создании относительной символической ссылки в другом месте, чем текущий каталог, разрешение символической ссылки будет отличаться от разрешения той же строки из текущего каталога. Поэтому многие пользователи предпочитают сначала изменить каталоги на место, где будет создана относительная символическая ссылка, чтобы завершение табуляции или другое разрешение файла находили ту же цель, что и размещенная в символической ссылке.

-- из info coreutils 'ln invocation'

Тем не менее, вы ДОЛЖНЫ использовать относительный или абсолютный путь к цели.

sparticvs
источник
5

Это действительно предполагаемое поведение. Со ln(1)страницы руководства :

Символьные ссылки могут содержать произвольный текст; если позже разрешено, относительная ссылка интерпретируется относительно его родительского каталога.

Что касается причины этого, представьте, что символическая ссылка вместо этого интерпретируется относительно ее источника, а не его назначения. При дальнейшем разрешении вам нужно будет знать, каким был ваш CWD, когда вы его создали, что бессмысленно, не говоря уже о невозможности.

Более того, таким образом вы получаете аккуратный и компактный метод для создания каркасной структуры каталогов, которую вы можете перетаскивать в любом месте дерева каталогов без разрыва символических ссылок.

Чтобы дать вам пример того, что я имею в виду, допустим, вы работаете над проектом и для него настроена целая структура каталогов, например:

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

Теперь предположим, что вы хотите создать символическую ссылку widgets/внутри wizardry/. У вас есть два варианта:

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

или

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

Если вы затем попытаетесь переместиться /home/you/projectкуда-нибудь еще, символическая ссылка, созданная с первой формой, прекратит работу, потому что ищет /home/you/project/widgets. Вторая форма сохранит функциональность символической ссылки, потому что она ищет ../widgets относительно места, в котором она находится, независимо от того, где это место может быть в дереве каталогов.

Джозеф Р.
источник