为什么在权限正常的情况下符号链接更新到新目标时权限被拒绝?

为什么在权限正常的情况下符号链接更新到新目标时权限被拒绝?

在一台 Linux 机器(实际上是一个计算集群)上,我从另一个用户那里复制了一个文件夹(他授予我使用适当的 chmod 执行此操作的权限)。

该文件夹包含我无法访问的文件的符号链接。我想更新它们,以便它们指向我拥有的相同文件的副本。

但是,当我尝试使用 这样做时ln -sf,我得到了Permission denied

为什么会这样?

这就是链接:

$ ls -l 50ATC_Rep2.fastq
lrwxrwxrwx 1 bli cifs-BioIT 55 21 nov.  13:45 50ATC_Rep2.fastq -> /pasteur/homes/mmazzuol/Raw_data/CHIP_TEST/BM50.2.fastq

我无权访问其目标,但我有它的副本。这就是我想要的新目标:

$ ls -l ../../../raw_data/CHIP_TEST/BM50.2.fastq
-rwxr-xr-x 1 bli cifs-BioIT 4872660831 21 nov.  14:00 ../../../raw_data/CHIP_TEST/BM50.2.fastq

这就是我尝试时发生的情况ln -sf

$ ln -sf ../../../raw_data/CHIP_TEST/BM50.2.fastq 50ATC_Rep2.fastq
ln: accessing `50ATC_Rep2.fastq': Permission denied

看来当前目标的权限才是重要的,而不是链接本身的权限。

我可以通过先删除链接然后重新创建它来规避该问题:

$ rm 50ATC_Rep2.fastq
rm: remove symbolic link `50ATC_Rep2.fastq'? y
$ ln -s ../../../raw_data/CHIP_TEST/BM50.2.fastq 50ATC_Rep2.fastq
$ ls -l 50ATC_Rep2.fastq
lrwxrwxrwx 1 bli cifs-BioIT 40 21 nov.  18:57 50ATC_Rep2.fastq -> ../../../raw_data/CHIP_TEST/BM50.2.fastq

为什么我可以删除链接,但无法更新?

答案1

看起来好像lnLinux 上的 GNU 实现使用了stat()函数判断目标是否存在。该函数需要解析符号链接,因此当无法访问预先存在的链接的目标时,该函数将返回EACCESS(“权限被拒绝”)并且实用程序失败。这已strace在 Ubuntu Linux 系统上得到验证。

让 GNUln使用lstat()相反,它不解析符号链接,您应该使用其(非标准)-n选项来调用它(GNU 另外用作 的--no-dereference别名-n)。

ln -s -n -f ../../../raw_data/CHIP_TEST/BM50.2.fastq 50ATC_Rep2.fastq

正在阅读POSIX 规范ln,我真的无法弄清楚 GNU 是否ln对规范中某些未定义或未指定的行为这样做,但它可能利用了这样一个事实……

如果目标路径存在并且是由上一步创建的,未指定是否ln应将诊断消息写入标准错误,对当前源文件不执行任何操作,并继续处理任何剩余的源文件;或将继续处理当前的source_file。

这里的“未指定”位可能会给予 GNUln其行为的许可,至少如果我们允许自己将“前一步”解释为“目标路径是符号链接”。

该选项的 GNU 文档-n主要关注目标是指向某个对象的符号链接的情况。目录

'-n'
'--no-dereference'
     Do not treat the last operand specially when it is a symbolic link
     to a directory.  Instead, treat it as if it were a normal file.

     When the destination is an actual directory (not a symlink to one),
     there is no ambiguity.  The link is created in that directory.  But
     when the specified destination is a symlink to a directory, there
     are two ways to treat the user's request.  'ln' can treat the
     destination just as it would a normal directory and create the link
     in it.  On the other hand, the destination can be viewed as a
     non-directory--as the symlink itself.  In that case, 'ln' must
     delete or backup that symlink before creating the new link.  The
     default is to treat a destination that is a symlink to a directory
     just like a directory.

     This option is weaker than the '--no-target-directory' ('-T')
     option, so it has no effect if both options are given.

当目标是目录的符号链接时, GNU 的默认行为ln是将新的符号链接放入该目录中(即,取消引用该目录的链接)。当预先存在的链接的目标不可访问时,它会选择发出诊断消息并失败(标准文本允许)。

另一方面,当目标是指向某个对象的符号链接时,OpenBSD ln(可能还有其他 BSD 系统)的行为将类似于 GNU。lnln无障碍目录,但如果预先存在的链接的目标是,则将根据请求取消链接并重新创建符号链接不是无障碍。即,它选择继续操作(标准文本允许)。

另外,lnOpenBSD 上的 GNU 的行为类似于 OpenBSD 的本机ln,这有点有趣。

删除预先存在的符号链接rm不是任何问题,因为您似乎对其所在目录具有写入和可执行权限。

相关内容