您可以在创建符号链接后更改它所指向的内容吗? [英] Can you change what a symlink points to after it is created?

查看:22
本文介绍了您可以在创建符号链接后更改它所指向的内容吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有任何操作系统提供一种机制(系统调用——不是命令行程序)来更改符号链接(符号链接)引用的路径名——而不是通过取消链接旧链接并创建新链接?

Does any operating system provide a mechanism (system call — not command line program) to change the pathname referenced by a symbolic link (symlink) — other than by unlinking the old one and creating a new one?

POSIX 标准没有.Solaris 10 没有.MacOS X 10.5 (Leopard) 没有.(我敢肯定 AIX 和 HP-UX 都不会.从 Linux 系统调用列表来看,Linux 也没有这样的系统调用.)

The POSIX standard does not. Solaris 10 does not. MacOS X 10.5 (Leopard) does not. (I'm tolerably certain neither AIX nor HP-UX does either. Judging from this list of Linux system calls, Linux does not have such a system call either.)

有什么可以做的吗?

(我期待答案是否".)

(I'm expecting that the answer is "No".)

既然证明否定很困难,那么让我们重新组织一下问题.

Since proving a negative is hard, let's reorganize the question.

如果您知道某些尚未列出的(类 Unix)操作系统没有系统调用来重写符号链接的值(readlink() 返回的字符串)而不删除旧的符号链接并创建一个新的,请在答案中添加它或它们.

If you know that some (Unix-like) operating system not already listed has no system call for rewriting the value of a symlink (the string returned by readlink()) without removing the old symlink and creating a new one, please add it — or them — in an answer.

推荐答案

AFAIK,不,你不能.您必须删除它并重新创建它. 实际上,您可以覆盖一个符号链接,从而更新它所引用的路径名:

AFAIK, no, you can't. You have to remove it and recreate it. Actually, you can overwrite a symlink and thus update the pathname referenced by it:

$ 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

EDIT:正如 OP 在评论中指出的那样,使用 --force 选项将使 ln 执行对 ln 的系统调用symlink() 之前的 code>unlink().下面,strace 在我的 linux 机器上的输出证明了这一点:

EDIT: As the OP pointed out in a comment, using the --force option will make ln perform a system call to unlink() before symlink(). Below, the output of strace on my linux box proving it:

$ 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

所以我想最后的答案是不".

编辑:以下内容是从 Arto Bendiken 的回答在 unix 上复制的.stackexchange.com,大约 2016 年.

EDIT: The following is copied from Arto Bendiken's answer over on unix.stackexchange.com, circa 2016.

可以确实可以通过rename(2)自动完成,首先在一个临时名称下创建新的符号链接,然后一次性干净地覆盖旧的符号链接.正如手册页所述:

This can indeed be done atomically with rename(2), by first creating the new symlink under a temporary name and then cleanly overwriting the old symlink in one go. As the man page states:

如果 newpath 引用一个符号链接,该链接将被覆盖.

If newpath refers to a symbolic link the link will be overwritten.

在 shell 中,您可以使用 mv -T 执行此操作,如下所示:

In the shell, you would do this with mv -T as follows:

$ mkdir a b
$ ln -s a z
$ ln -s b z.new
$ mv -T z.new z

您可以strace最后一个命令以确保它确实在后台使用了rename(2):

You can strace that last command to make sure it is indeed using rename(2) under the hood:

$ 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 都是 Linux 特定的.

Note that in the above, both mv -T and strace are Linux-specific.

在 FreeBSD 上,交替使用 mv -h.

On FreeBSD, use mv -h alternately.

编者注:这是 Capistrano 多年来一直这样做的方式,自 2.15 以来.请参阅此拉取请求.

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

这篇关于您可以在创建符号链接后更改它所指向的内容吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆