Можно ли изменить то, на что символьная ссылка указывает на то, после того, как она создается?

Никакое значение фиксированной длины никогда не может гарантировать, что было на 100% уникально (просто называют его достаточно раз, плюс-минус окончание вселенной;-p) - но это может быть очень, очень, очень вряд ли для дублирования.

119
задан Jonathan Leffler 24 December 2014 в 16:55
поделиться

3 ответа

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

$ ln -s .bashrc test
$ ls -al test
lrwxrwxrwx 1 pascal pascal 7 2009-09-23 17:12 test -> .bashrc
$ ln -s .profile test
ln: creating symbolic link `test': File exists
$ ln -s -f .profile test
$ ls -al test
lrwxrwxrwx 1 pascal pascal 8 2009-09-23 17:12 test -> .profile

EDIT : как OP указал в комментарии, использование параметра - force сделает ln выполняет системный вызов unlink () перед symlink () . Ниже вывод strace на моем Linux-боксе, подтверждающий это:

$ strace -o /tmp/output.txt ln -s -f .bash_aliases test
$ grep -C3 ^unlink /tmp/output.txt 
lstat64("test", {st_mode=S_IFLNK|0777, st_size=7, ...}) = 0
stat64(".bash_aliases", {st_mode=S_IFREG|0644, st_size=2043, ...}) = 0
symlink(".bash_aliases", "test")        = -1 EEXIST (File exists)
unlink("test")                          = 0
symlink(".bash_aliases", "test")        = 0
close(0)                                = 0
close(1)                                = 0

Итак, я предполагаю, что окончательный ответ - «нет».

РЕДАКТИРОВАТЬ : Следующее скопировано из Arto Ответ Бендикена на unix.stackexchange.com, около 2016 года.

Это действительно может быть выполнено атомарно с помощью rename (2) , сначала создав новую символическую ссылку под временным именем, а затем полностью перезаписав старую символическую ссылку за один раз. Как указано на странице руководства :

Если newpath ссылается на символическую ссылку, ссылка будет перезаписана.

В оболочке вы должны сделать это с помощью mv -T следующим образом:

$ mkdir a b
$ ln -s a z
$ ln -s b z.new
$ mv -T z.new z

Вы можете strace эту последнюю команду, чтобы убедиться, что она действительно использует rename (2) под капотом:

$ strace mv -T z.new z
lstat64("z.new", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
lstat64("z", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
rename("z.new", "z")                    = 0

Обратите внимание, что в как указано выше, mv -T и strace специфичны для Linux.

Во FreeBSD используйте поочередно mv -h .

Примечание редактора: Так Капистрано делал это уже много лет, начиная с ~ 2.15. См. этот запрос на перенос .

Как указано на странице руководства :

Если newpath ссылается на символическую ссылку, ссылка будет перезаписана.

В оболочке вы должны сделать это с помощью mv -T следующим образом:

$ mkdir a b
$ ln -s a z
$ ln -s b z.new
$ mv -T z.new z

Вы можете strace эту последнюю команду, чтобы убедиться, что она действительно использует rename (2) под капотом:

$ strace mv -T z.new z
lstat64("z.new", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
lstat64("z", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
rename("z.new", "z")                    = 0

Обратите внимание, что в как указано выше, и mv -T , и strace специфичны для Linux.

Во FreeBSD используйте поочередно mv -h .

Примечание редактора: Так Капистрано делал это уже много лет, начиная с ~ 2.15. См. этот запрос на перенос .

Как указано на странице руководства :

Если newpath ссылается на символическую ссылку, ссылка будет перезаписана.

В оболочке вы должны сделать это с помощью mv -T следующим образом:

$ mkdir a b
$ ln -s a z
$ ln -s b z.new
$ mv -T z.new z

Вы можете strace эту последнюю команду, чтобы убедиться, что она действительно использует rename (2) под капотом:

$ strace mv -T z.new z
lstat64("z.new", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
lstat64("z", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
rename("z.new", "z")                    = 0

Обратите внимание, что в как указано выше, и mv -T , и strace специфичны для Linux.

Во FreeBSD используйте поочередно mv -h .

Примечание редактора: Так Капистрано делал это уже много лет, начиная с ~ 2.15. См. этот запрос на перенос .

$ mkdir a b
$ ln -s a z
$ ln -s b z.new
$ mv -T z.new z

Вы можете strace эту последнюю команду, чтобы убедиться, что она действительно использует rename (2) под капотом:

$ strace mv -T z.new z
lstat64("z.new", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
lstat64("z", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
rename("z.new", "z")                    = 0

Обратите внимание, что в приведенном выше примере оба mv -T и strace специфичны для Linux.

Во FreeBSD используйте поочередно mv -h .

Примечание редактора: Так Капистрано делал это уже много лет, начиная с ~ 2.15. См. этот запрос на перенос .

$ mkdir a b
$ ln -s a z
$ ln -s b z.new
$ mv -T z.new z

Вы можете strace эту последнюю команду, чтобы убедиться, что она действительно использует rename (2) под капотом:

$ strace mv -T z.new z
lstat64("z.new", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
lstat64("z", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
rename("z.new", "z")                    = 0

Обратите внимание, что в приведенном выше примере оба mv -T и strace специфичны для Linux.

Во FreeBSD используйте поочередно mv -h .

Примечание редактора: Так Капистрано делал это уже много лет, начиная с ~ 2.15. См. этот запрос на перенос .

100
ответ дан 24 November 2019 в 01:47
поделиться

Нет необходимости явно отключать старую символическую ссылку. Вы можете сделать это:

ln -s newtarget temp
mv temp mylink

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

В некоторых файловых системах цель символической ссылки сохраняется в самом индексном дескрипторе (вместо списка блоков), если он достаточно короткий; это определяется во время создания.

Что касается утверждения, что фактический владелец и группа не имеют значения, символическая ссылка (7) в Linux говорит, что есть случай, когда это имеет значение:

] Владелец и группу существующей символической ссылки можно изменить с помощью lchown (2). Единственный раз, когда право собственности на символическую ссылку имеет значение, это когда ссылка удаляется или переименовывается в каталоге с прикрепленным установлен бит (см. stat (2)).

Временные метки последнего доступа и последнего изменения символьной ссылки могут быть изменено с помощью utimensat (2) или lutimes (3).

В Linux разрешения символьной ссылки не используются ни в каких операциях; разрешения всегда 0777 (чтение, запись и выполнение для всех пользователей категории) и не могут быть изменены.

12
ответ дан 24 November 2019 в 01:47
поделиться

Разве отключение и создание новой связи в любом случае не приведет к тому же результату?

1
ответ дан 24 November 2019 в 01:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: