Programing

심볼릭 링크가 작성된 후 가리키는 것을 변경할 수 있습니까?

lottogame 2020. 7. 15. 07:38
반응형

심볼릭 링크가 작성된 후 가리키는 것을 변경할 수 있습니까?


운영 체제에서 이전 링크를 연결 해제하고 새 링크를 작성하는 것 이외의 기호 링크 (symlink)로 참조되는 경로 이름을 변경하는 메커니즘 (시스템 호출-명령 행 프로그램 아님)을 제공합니까?

POSIX 표준은 그렇지 않습니다. 솔라리스 10은 그렇지 않습니다. MacOS X 10.5 (Leopard)는 그렇지 않습니다. (저는 AIX 나 HP-UX도 마찬가지입니다.이 Linux 시스템 호출 목록에서 판단 할 때 Linux에는 그러한 시스템 호출도 없습니다.)

어떤 것이 있습니까?

(답은 "아니오"라고 기대합니다.)


부정적인 것을 증명하는 것은 어렵 기 때문에 질문을 재구성 해 봅시다.

아직 나열되지 않은 (유닉스 계열) 일부 운영 체제 readlink()에 이전 symlink를 제거하고 새 symlink를 작성하지 않고 symlink (문자열에서 반환 한 문자열)의 값을 다시 써야하는 시스템 호출이없는 경우이를 추가하십시오. 대답으로.


AFAIK, 아니오, 당신은 할 수 없습니다. 제거하고 다시 만들어야합니다. 실제로 심볼릭 링크를 덮어 써서 참조하는 경로 이름을 업데이트 할 수 있습니다.

$ 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

편집 : 의견에서 OP가 지적한 것처럼 --force옵션을 사용하면 이전에 ln시스템 호출을 수행합니다 . 아래의 리눅스 박스 출력 결과는 다음과 같습니다.unlink()symlink()strace

$ 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

최종 답변은 "아니오"라고 생각합니다.

편집 : 다음은 2016 년경 unix.stackexchange.com에 대한 Arto Bendiken의 답변 에서 복사 한 것 입니다.

이는 임시 이름으로 새 심볼릭 링크를 만든 다음 이전 심볼릭 링크를 한 번에 완전히 덮어 써서 실제로 원자 적으로 수행 할 수 있습니다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 -Tstrace리눅스 다릅니다.

FreeBSD에서는 mv -h교대로 사용하십시오 .

Editor's note: This is how Capistrano has done it for years now, ever since ~2.15. See this pull request.


Yes, you can!

$ ln -sfn source_file_or_directory_name softlink_name

It is not necessary to explicitly unlink the old symlink. You can do this:

ln -s newtarget temp
mv temp mylink

(or use the equivalent symlink and rename calls). This is better than explicitly unlinking because rename is atomic, so you can be assured that the link will always point to either the old or new target. However this will not reuse the original inode.

On some filesystems, the target of the symlink is stored in the inode itself (in place of the block list) if it is short enough; this is determined at the time it is created.

Regarding the assertion that the actual owner and group are immaterial, symlink(7) on Linux says that there is a case where it is significant:

The owner and group of an existing symbolic link can be changed using lchown(2). The only time that the ownership of a symbolic link matters is when the link is being removed or renamed in a directory that has the sticky bit set (see stat(2)).

The last access and last modification timestamps of a symbolic link can be changed using utimensat(2) or lutimes(3).

On Linux, the permissions of a symbolic link are not used in any operations; the permissions are always 0777 (read, write, and execute for all user categories), and can't be changed.


Just a warning to the correct answers above:

Using the -f / --force Method provides a risk to lose the file if you mix up source and target:

mbucher@server2:~/test$ ls -la
total 11448
drwxr-xr-x  2 mbucher www-data    4096 May 25 15:27 .
drwxr-xr-x 18 mbucher www-data    4096 May 25 15:13 ..
-rw-r--r--  1 mbucher www-data 4109466 May 25 15:26 data.tar.gz
-rw-r--r--  1 mbucher www-data 7582480 May 25 15:27 otherdata.tar.gz
lrwxrwxrwx  1 mbucher www-data      11 May 25 15:26 thesymlink -> data.tar.gz
mbucher@server2:~/test$ 
mbucher@server2:~/test$ ln -s -f thesymlink otherdata.tar.gz 
mbucher@server2:~/test$ 
mbucher@server2:~/test$ ls -la
total 4028
drwxr-xr-x  2 mbucher www-data    4096 May 25 15:28 .
drwxr-xr-x 18 mbucher www-data    4096 May 25 15:13 ..
-rw-r--r--  1 mbucher www-data 4109466 May 25 15:26 data.tar.gz
lrwxrwxrwx  1 mbucher www-data      10 May 25 15:28 otherdata.tar.gz -> thesymlink
lrwxrwxrwx  1 mbucher www-data      11 May 25 15:26 thesymlink -> data.tar.gz

Of course this is intended, but usually mistakes occur. So, deleting and rebuilding the symlink is a bit more work but also a bit saver:

mbucher@server2:~/test$ rm thesymlink && ln -s thesymlink otherdata.tar.gz 
ln: creating symbolic link `otherdata.tar.gz': File exists

which at least keeps my file.


Wouldn't unlinking it and creating the new one do the same thing in the end anyway?


Just in case it helps: there is a way to edit a symlink with midnight commander (mc). The menu command is (in French on my mc interface):

Fichier / Éditer le lien symbolique

which may be translated to:

File / Edit symbolic link

The shortcut is C-x C-s

Maybe it internally uses the ln --force command, I don't know.

Now, I'm trying to find a way to edit a whole lot of symlinks at once (that's how I arrived here).


Technically, there's no built-in command to edit an existing symbolic link. It can be easily achieved with a few short commands.

Here's a little bash/zsh function I wrote to update an existing symbolic link:

# -----------------------------------------
# Edit an existing symbolic link
#
# @1 = Name of symbolic link to edit
# @2 = Full destination path to update existing symlink with 
# -----------------------------------------
function edit-symlink () {
    if [ -z "$1" ]; then
        echo "Name of symbolic link you would like to edit:"
        read LINK
    else
        LINK="$1"
    fi
    LINKTMP="$LINK-tmp"
    if [ -z "$2" ]; then
        echo "Full destination path to update existing symlink with:"
        read DEST
    else
        DEST="$2"
    fi
    ln -s $DEST $LINKTMP
    rm $LINK
    mv $LINKTMP $LINK
    printf "Updated $LINK to point to new destination -> $DEST"
}

참고URL : https://stackoverflow.com/questions/1466566/can-you-change-what-a-symlink-points-to-after-it-is-created

반응형