Unix 创建符号链接后,是否可以更改其指向的内容?
是否有操作系统提供了一种机制(系统调用-不是命令行程序)来更改符号链接(symlink)引用的路径名,而不是通过断开旧的链接并创建新的路径名 POSIX标准没有。Solaris 10没有。MacOS X 10.5(Leopard)没有。(我可以相当肯定AIX和HP-UX都没有。从这个列表中可以看出,Linux也没有这样的系统调用。) 有什么有用的吗 (我希望答案是“不”。)Unix 创建符号链接后,是否可以更改其指向的内容?,unix,symlink,Unix,Symlink,是否有操作系统提供了一种机制(系统调用-不是命令行程序)来更改符号链接(symlink)引用的路径名,而不是通过断开旧的链接并创建新的路径名 POSIX标准没有。Solaris 10没有。MacOS X 10.5(Leopard)没有。(我可以相当肯定AIX和HP-UX都没有。从这个列表中可以看出,Linux也没有这样的系统调用。) 有什么有用的吗 (我希望答案是“不”。) 既然证明否定是困难的,让我们重新组织这个问题 如果您知道尚未列出的某些(类Unix)操作系统没有系统调用来重写符号链接的
既然证明否定是困难的,让我们重新组织这个问题 如果您知道尚未列出的某些(类Unix)操作系统没有系统调用来重写符号链接的值(由
readlink()
返回的字符串),而不删除旧的符号链接并创建新的符号链接,请在回答中添加它或它们。好的,不,您不能。您必须删除它并重新创建它。实际上,您可以覆盖符号链接,从而更新其引用的路径名:
$ 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
在symlink()
之前执行系统调用unlink()
。下面是我的linux机器上的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
所以我猜最后的答案是“不”
编辑:以下是从unix.stackexchange.com上复制的,大约在2016年
通过使用重命名(2)
,首先在临时名称下创建新的符号链接,然后一次性完全覆盖旧的符号链接,这确实可以原子化地完成。作为缔约国:
如果newpath引用符号链接,则该链接将被覆盖
在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
编者按:这是Capistrano多年来一直在做的事情,从~2.15开始。请参阅。取消链接并创建新符号链接最终不会做同样的事情吗?没有必要显式取消链接旧符号链接。您可以这样做:
ln -s newtarget temp
mv temp mylink
(或使用等效的符号链接和重命名调用)。这比显式取消链接要好,因为重命名是原子的,所以可以确保链接始终指向旧的或新的目标。但是,这不会重用原始inode
在某些文件系统上,如果符号链接的目标足够短,则将其存储在inode本身(代替块列表)中;这是在创建时确定的
关于实际所有者和组无关紧要的说法,on Linux表示,有一种情况非常重要:
可以使用更改现有符号链接的所有者和组
立法会(二)。符号链接的所有权唯一重要的时候是
在具有粘性的目录中删除或重命名链接时
位集(见stat(2))
符号链接的最后访问和最后修改时间戳可以是
使用utimensat(2)或lutimes(3)进行更改
在Linux上,符号链接的权限不用于任何操作;
所有用户的权限始终为0777(读、写和执行)
类别),并且无法更改
是的,你可以
$ ln -sfn source_file_or_directory_name softlink_name
以上正确答案只是一个警告: 如果混淆了源和目标,则使用-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
它至少保存了我的文件。以防万一:有一种方法可以使用midnight commander(mc)编辑符号链接。 菜单命令为(在我的mc界面上为法语): 可翻译为:
File / Edit symbolic link
快捷方式是C-x C-s
也许它在内部使用了ln--force
命令,我不知道
现在,我正试图找到一种方法,一次编辑大量符号链接(我就是这样来到这里的)。从技术上讲,没有内置命令来编辑现有的符号链接。只需几个简短的命令即可轻松实现 这里有一个小的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"
}
简单地重新链接有什么问题?为什么不发出
ln
命令(或API Equivalent)覆盖旧链接?你有什么问题?有趣-我在问是否有系统调用来执行编程工作,并且问题被标记为“属于其他站点”。有趣的是-根本不清楚你在寻找系统调用,你只是编辑了问题以添加此细节。那么,你怎么能指望人们在你写东西之前就把它删掉呢?@S.Lott:我正在写一篇关于安全和符号链接的论文。我曾断言“符号链接本身的实际所有者、组和权限是无关紧要的”,理由是符号链接的所有者只能删除它,而不能更改值。我反复检查,除了删除符号链接之外,没有其他方法可以达到“重写符号链接值”的效果。我忽略了对原始磁盘的直接访问,并以这种方式攻击FS-这需要root权限,我关心的是非root用户,而不是root用户可以做什么。@Pascal:对不起-直到人们偏离了我的意图,我才意识到我说的是系统调用(这显然与我所说的不同)。很抱歉我误导了你,这是无意的。为什么首先要取消链接?为什么不
# -----------------------------------------
# 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"
}