我正在尝试(尽可能接近)原子地更改符号链接。我试过了:
ln -sf other_dir existing_symlink
这只是将新的符号链接放入execution_symlink 指向的目录中。
ln -sf other_dir new_symlink
mv -f new_symlink existing_symlink
这做了同样的事情:它将符号链接移动到目录中。
cp -s other_dir existing_symlink
它拒绝,因为它是一个目录。
我读过这mv -T
是为此而设计的,但 busybox 没有该-T
标志。
答案1
这能rename(2)
实际上可以通过首先以临时名称创建新的符号链接,然后一次性干净地覆盖旧的符号链接来自动完成。作为手册页状态:
如果新路径引用符号链接时该链接将被覆盖。
在 shell 中,您可以按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
从 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://axiscorps.wordpress.com/2013/07/03/atomically-replacing-files-and-directories/)
答案3
你有没有尝试过ln -snf
?
-n
当目标是目录的符号链接时,该选项会覆盖目标而不是在目标下写入。
干杯
答案4
我不明白如何获得原子操作。的手册页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'
我认为您必须分两步执行此操作:删除旧的符号链接并重新创建它。