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

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

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깃발 이 없습니다 .



답변

원자 작전을 얻는 방법을 모르겠습니다. 의 매뉴얼 페이지에 대상이 이미 존재하는지 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'

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


답변

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


답변

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


답변

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

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

건배


답변