busybox의 디렉토리에 대한 심볼릭 링크를 원자 적으로 어떻게 변경합니까?


18

원자 적으로 심볼릭 링크를 변경하려고합니다. 난 노력 했어:

ln -sf other_dir existing_symlink

기존의 symlink가 가리키는 디렉토리에 새로운 심볼릭 링크를 넣으면됩니다.

ln -sf other_dir new_symlink
mv -f new_symlink existing_symlink

그것은 같은 일을했습니다 : 그것은 심볼릭 링크를 디렉토리로 옮겼습니다.

cp -s other_dir existing_symlink

디렉토리이기 때문에 거부합니다.

나는 이것을 mv -T위해 만들어진 것을 읽었 지만 busybox에는 -T깃발 이 없습니다 .

답변:


1

원자 작전을 얻는 방법을 모르겠습니다. 의 매뉴얼 페이지에 대상이 이미 존재하는지 symlink(2)알려줍니다 EEXIST. 커널이 원자 연산을 지원하지 않으면, 사용자 영역 제한은 관련이 없습니다.

또한 mv -T도움이 필요하더라도 도움 이되지 않습니다 . GNU mv가있는 일반 Linux 상자에서 사용해보십시오.

$ mkdir a b
$ ln -s a z
$ mv -T b z
mv: cannot overwrite non-directory `z' with directory `b'

나는 당신이 두 단계 로이 작업을 수행해야한다고 생각합니다 : 이전 심볼릭 링크를 제거하고 다시 만드십시오.


1
실제로 불행히도 기호를 원자 적으로 수정할 수있는 방법은 없습니다. 가장 좋은 방법은 기존 링크를 제거하고 새 링크를 만드는 것입니다. GNU coreutils에는 단일 명령 ( ln -snf)으로 이를 수행 할 수있는 옵션이 있지만 여전히 두 가지 시스템 호출이 있습니다.
Gilles 'SO- 악마 중지'12

43

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


1
아주 좋아요! 끝에 z에서 b ​​로의 링크가 있다고 말하는 것이 도움이 될 수 있습니다!
Vincenzo Pii

OS 독립적 솔루션의 경우 또는 rename대신 syscall을 직접 사용할 수있는 스크립팅 언어를 사용하십시오 . 예를 들어 Perl :mv -hmv -Tperl -e 'rename "z.new", "z" or die $!'
Slaven Rezic

8

Arto가 여기서 벗어난 곳을 선택하면 이것이 없이도 가능 mv -T합니다. 대상 디렉토리와 이름이 같은 새 심볼릭 링크를 대상 디렉토리 mv의 부모 디렉토리에 만들어야합니다 .

mkdir -p tmp/real_dir1 tmp/real_dir2
touch tmp/real_dir1/a tmp/real_dir2/a
# start with ./target_dir pointing to tmp/real_dir1
ln -s tmp/real_dir1 target_dir
# create a symlink named target_dir in tmp, pointing to real_dir2
ln -sf tmp/real_dir2 tmp/target_dir
# atomically mv it into ./ replacing ./target_dir
mv tmp/target_dir ./

(을 통해 가져온 코드 예제 http://axialcorps.wordpress.com/2013/07/03/atomically-replacing-files-and-directories/ )


3

당신이 시도 했습니까 ln -snf ?

옵션 -n 대상이 디렉토리에 대한 심볼릭 링크 인 경우 그 아래에 대상이 아닌 글을 덮어 씁니다.

건배


3
ln -snf원자가 아닙니다. 대상을 연결 해제 한 다음 원하는 심볼릭 링크를 만듭니다.
Gilles 'SO- 악한 중지'

2
OP가 원자 적으로 심볼릭 링크를 변경하는 데 "가능한 한 가깝게"하는 데 관심이 있다는 것을 감안할 때 이것은 완벽하게 합리적인 답변입니다. 더 가깝거나 원자가 될 수있는 더 좋은 것이 있다면 받아 들여질 수 있습니다. 공감할 필요가 없다고 생각합니다.
Wilco
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.