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


122

어떤 운영 체제에서 이전 링크를 해제하고 새 링크를 만드는 것 외에 기호 링크 (symlink)가 참조하는 경로 이름을 변경하는 메커니즘 (명령 줄 프로그램이 아닌 시스템 호출)을 제공합니까?

POSIX 표준은 그렇지 않습니다. Solaris 10은 그렇지 않습니다. MacOS X 10.5 (Leopard)는 그렇지 않습니다. (나는 AIX 나 HP-UX도 마찬가지라고 확신합니다.이 Linux 시스템 호출 목록에서 볼 때 Linux에도 그러한 시스템 호출이 없습니다.)

하는 일이 있습니까?

(나는 대답이 "아니오"라고 예상하고 있습니다.)


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

아직 나열되지 않은 일부 (유닉스 계열) 운영 체제 readlink()에 이전 심볼릭 링크를 제거하고 새 심볼릭 링크를 생성하지 않고 심볼릭 링크 (에서 반환 된 문자열) 값을 다시 쓰기위한 시스템 호출이 없다는 것을 알고있는 경우 추가하십시오. 대답.


단순히 다시 연결하는 것이 잘못된 것은 무엇입니까? ln명령 (또는 이에 상응하는 API)을 실행하여 이전 링크를 덮어 쓰지 않는 이유는 무엇 입니까? 어떤 문제가 있습니까?
S.Lott

9
웃기다-프로그래밍 작업을 수행하는 시스템 호출이 있는지 묻고 있는데 질문이 '다른 사이트에 속함'으로 표시됩니다.
Jonathan Leffler

3
웃긴-시스템 호출을 찾고있는 것이 분명하지 않았고이 세부 사항을 추가하기 위해 질문을 편집했습니다. 그렇다면 글을 쓰기도 전에 사람들이 무언가를 공제하기를 어떻게 기대할 수 있습니까?
Pascal Thivent

2
@ S.Lott : 보안 및 심볼릭 링크에 대한 논문을 작성하고 있습니다. 어느 시점에서 나는 "실제 소유자, 그룹, 심볼릭 링크 자체에 대한 권한은 중요하지 않다"고 주장하고 그 이유는 심볼릭 링크의 소유자가 심볼릭 링크를 제거 할 수만 있고 값을 변경할 수 없다는 것입니다. 나는 '심볼 링크 값 다시 쓰기'의 효과를 달성하는 심볼릭 링크를 제거하는 것 외에 다른 방법이 없다는 것을 다시 확인하고 있습니다. 나는 원시 디스크에 대한 직접 액세스를 무시하고 FS를 해킹합니다. 루트 권한이 필요하며 루트가 할 수있는 작업이 아니라 루트 권한이없는 사용자에 대한 우려가 있습니다.
Jonathan Leffler

4
@Pascal : 미안합니다. 사람들이 제가 의도 한 것 (내가 말한 것과 분명히 다른 것임)과 접할 때까지 시스템 호출에 대해 이야기하고 있다는 것이 분명하지 않다는 것을 깨닫지 못했습니다. 잘못 인도해서 미안합니다. 의도하지 않았습니다.
Jonathan Leffler

답변:


106

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교대로 사용하십시오 .

편집자 주 : 이것이 Capistrano가 ~ 2.15 이후 수년 동안해온 방법입니다. 이 pull 요청을 참조하십시오 .


2
'-f'옵션은 'ln'이 unlink () 다음 symlink () 시스템 호출을 수행하도록 강제하지 않습니까?
Jonathan Leffler

1
그렇습니다. 그러나 질문은 "어떻게 한 단계에서 수행 할 수 있는가"로 인식되었을 수 있으며 "단계"(명령 줄)의 정의로 귀결 될 수 있습니다. syscall?
Michael Krelin-해커

1
난 그냥 당신이 ;-) 질문에 콜 문구를 추가 한 것으로 나타났습니다
마이클 Krelin - 해커

2
@Pascal : 그렇습니다. Solaris에서 'truss ln -spx'및 'truss ln -s -fpx'의 출력은 두 번째 경우에 symlink () 호출 이전에 unlink () 호출을 보여줍니다 (첫 번째 경우에는 실패한 symlink () 호출). 나는 그것이 모든 유닉스 변형은 아니지만 대부분의 경우에 적용될 것으로 기대합니다.
Jonathan Leffler

12
@Taai 주석에 +1-디렉토리를 역 참조하는 (가리키는) 심볼릭 링크를 처리하는 경우이 트릭이 작동하는지 확인하려면 "-n"을 지정해야합니다.
wally

161

그래 넌 할수있어!

$ ln -sfn source_file_or_directory_name softlink_name

9
응답 해 주셔서 감사합니다. 이 -f옵션은 새 대상을 만들기 전에 '기존 대상 제거'를 의미합니다. 그래서,이 명령 만 수행하여 결과를 달성 unlink(2)다음을 symlink(2). 이것은 원래의 질문에 관한 것이 아닙니다. 또한 허용 대답하고 다음으로 모두 사용 대답 선정주의 ln -sf일을하기를하지만, 같은 strace출력을 보여줍니다, 그것은 수행 unlink()하고 symlink()심볼릭 링크를 수정하는 시스템 호출이 없기 때문에.
Jonathan Leffler

17
-n은 원래 링크가 파일 대신 디렉토리로 이동할 때 필요한 것으로 보입니다.
steampowered

11
'n'스위치가 중요합니다. 나는 symlink가 업데이트되지 않았지만 'no derefencing'옵션이 설정되지 않았기 때문에 명령이 기존 링크 안에 또 다른 링크를 생성한다는 문제로 고생했습니다.
Jonathan Gruber 2014

14

이전 심볼릭 링크를 명시 적으로 링크 해제 할 필요는 없습니다. 다음과 같이 할 수 있습니다.

ln -s newtarget temp
mv temp mylink

(또는 동등한 심볼릭 링크를 사용하고 호출 이름을 바꿉니다). 이름 변경은 원자 적이므로 명시 적으로 링크를 해제하는 것보다 낫습니다. 따라서 링크가 항상 이전 또는 새 대상을 가리킬 것임을 확신 할 수 있습니다. 그러나 이것은 원래 inode를 재사용하지 않습니다.

일부 파일 시스템에서 심볼릭 링크의 대상은 충분히 짧은 경우 inode 자체 (차단 목록 대신)에 저장됩니다. 이것은 생성 될 때 결정됩니다.

실제 소유자와 그룹이 중요하지 않다는 주장과 관련하여 Linux의 symlink (7) 는 중요한 경우가 있다고 말합니다.

lchown (2)을 사용하여 기존 심볼릭 링크의 소유자와 그룹을 변경할 수 있습니다. 심볼릭 링크의 소유권이 중요한 유일한 경우는 고정 비트가 설정된 디렉토리에서 링크를 제거하거나 이름을 바꿀 때입니다 (stat (2) 참조).

심볼릭 링크의 마지막 액세스 및 마지막 수정 타임 스탬프는 utimensat (2) 또는 lutimes (3)를 사용하여 변경할 수 있습니다.

Linux에서 심볼릭 링크의 권한은 어떤 작업에도 사용되지 않습니다. 권한은 항상 0777 (모든 사용자 범주에 대해 읽기, 쓰기 및 실행)이며 변경할 수 없습니다.


@ mark4o : 좋은 점-lchown ()에 대한 참조와 sticky-it 디렉토리의 소유권이 유용합니다. 감사합니다. 나는 lchown ()에 대해 알고 있었고 그것은 내 논문에 중요하지 않았습니다. 나는 또한 sticky-bit 디렉토리를 알고 있었다. 소유권은 규칙의 거의 표준적인 결과라고 생각합니다. 차이점과 아마도 그것이 호출되는 이유는 일반적으로 파일에 쓸 수 있으면 파일을 제거 할 수 있고 명목상 누구나 심볼릭 링크에 쓸 수 있다는 것입니다. 777 권한 중 하나이지만이 경우 규칙이 약간 다릅니다.
Jonathan Leffler

1
@ mark4o : The Not So Good-표시된 명령 시퀀스는 사용자가 생각하는대로 수행하지 않습니다 (최소한 시나리오에서는 set -x -e; mkdir junk; ( cd junk; mkdir olddir newdir; ln -s olddir mylink; ls -ilR; ln -s newdir temp; ls -ilR; mv temp mylink; ls -ilR; ); rm -fr junk). 디렉토리 대신 oldfile 및 newfile 파일을 만들고 동등한 스크립트를 실행하면 (주로 olddir을 oldfile로, newdir을 newfile로 변경) 예상했던 효과를 얻을 수 있습니다. 하나의 추가 복잡성! 응답 해 주셔서 감사합니다.
Jonathan Leffler

2

위의 정답에 대한 경고 :

-f / --force 메서드를 사용하면 소스와 대상이 섞일 경우 파일이 손실 될 위험이 있습니다.

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

물론 이것은 의도 된 것이지만 일반적으로 실수가 발생합니다. 따라서 심볼릭 링크를 삭제하고 재 구축하는 것은 조금 더 많은 작업이지만 약간의 절약 효과도 있습니다.

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

적어도 내 파일을 유지합니다.


-f또는 --force옵션을 사용하는 것은 항상 약간 위험합니다. 사용자가 자신의 내용을 알고 있다고 가정합니다. 습관적으로 사용하면 두 배로 치명적입니다 ( rm -fr …매번 위험합니다).
Jonathan Leffler 2014 년

1

연결을 해제하고 새로운 것을 생성하면 결국 동일한 작업을 수행하지 않겠습니까?


2
애초에 연결을 해제하는 이유는 무엇입니까? 간단하게 덮어 쓰지 않는 이유는 무엇입니까?
S.Lott

5
최종 결과는 거의 동일하지만 일반적으로 소유자와 그룹 및 마지막 수정 시간 (및 아마도 inode 번호)은 모두 다릅니다.
Jonathan Leffler

2
@ S.Lott : '덮어 쓰는'시스템 호출은 무엇입니까? POSIX에는 그러한 호출이 없습니다. Solaris 및 MacOS X에는 그러한 호출이 없습니다. Linux, AIX, HP-UX, Unix처럼 보이는 다른 모든 작업에 대한 호출이 있습니까? Windows는 AFAICT와 같은 방식으로 심볼릭 링크를 가지고 있지 않으므로 분석에 중요하지는 않지만 동등한 Windows API에 대한 정보가 유용 할 것입니다.
Jonathan Leffler

@Jonathan Leffler : 음 .... ln --force명령은 기존 링크를 완전히 덮어 씁니다.
S.Lott

여러분, 저는 당신이 교차 목적으로 말하는 것 같아요. S.Lott는 실행 파일에 대해 논의하고 ln (1)있으며 Matt b. 덮어 쓰기를 지원 symlink (2)하지 않는 사실을 논의하고 있습니다. 두 분 모두 옳습니다.의 구현을 ln (1)보면 unlink-relink 절차를 수행하는 가장 idomatic 방법이 제공 될 것입니다.
dmckee --- 전 중재자 새끼 고양이

0

도움이되는 경우 : midnight commander (mc)와 함께 심볼릭 링크를 편집하는 방법이 있습니다. 메뉴 명령은 다음과 같습니다 (mc 인터페이스에서 프랑스어).

Fichier / Éditer le lien symbolique

다음으로 번역 될 수 있습니다.

File / Edit symbolic link

단축키는 Cx Cs입니다.

아마도 내부적으로 ln --force명령을 사용하는 것 같습니다.

이제는 한 번에 많은 심볼릭 링크를 편집하는 방법을 찾으려고합니다.


1
MC가 무대 뒤에서 무엇을하는지 확인 했습니까? 나는 그것이 유닉스 계열 시스템이 제공하는 것이기 때문에 실제로 unlink()뒤에 a를 수행 할 가능성이 symlink()있습니다.
Jonathan Leffler

아니요, 확인하지 않았습니다. 그리고 네, 사실 당신이 말한대로 할 가능성이 매우 높습니다. 내가 텍스트 상자를 편집한다는 사실은 내가 실제로 심볼릭 링크 대상을 편집하고 있다는 느낌을 주지만 아마 속았을 것입니다 ...
Pierre

0

기술적으로 기존 심볼릭 링크를 편집하는 기본 제공 명령이 없습니다. 몇 가지 짧은 명령으로 쉽게 달성 할 수 있습니다.

다음 은 기존 심볼릭 링크를 업데이트하기 위해 작성한 작은 bash / zsh 함수입니다 .

# -----------------------------------------
# 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"
}

2
노력 해주셔서 감사합니다. 이것은 C 언어 시스템 호출에 대한 요구 사항을 충족하지 않습니다. 링크를 보유한 디렉토리에 대한 쓰기 권한이있는 한 링크를 변경하는 방법은 여러 가지가 있습니다 (필요한 경우). 거기에 나는, 지금도 알고하지 않고 심볼릭 링크의 값을 변경 아무 방법 unlink()symlink()코드와 함께 배후에가는 것입니다 새 값으로한다. 개인적으로 나는 함수가 정확히 두 개 (또는 두 개의 배수) 인수를 주장하고 호출이 올바르지 않으면 보석금을 내도록 할 것입니다. 하지만 그것은 특별한 관점입니다.
Jonathan Leffler
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.