為什麼在將符號連結更新到具有權限的新目標時權限被拒絕?
在 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
為什麼我可以刪除連結,但不能更新?
似乎
ln
Linux 上的 GNU 實現使用該stat()
函式來確定目標是否存在。此函式是解析符號連結所必需的,因此當無法訪問預先存在的連結的目標時,該函式返回EACCESS
(“權限被拒絕”)並且實用程序失敗。這已strace
在 Ubuntu Linux 系統上得到驗證。要改為
ln
使用lstat()
不解析符號連結的 GNU,您應該使用其(非標準)-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 不做任何事情,並繼續處理任何剩餘的 source_files;或將繼續處理目前的 source_file。此處的“未指定”位可能會授予 GNU
ln
行為的許可,至少如果我們允許自己將“前一步”解釋為“目標路徑是符號連結”。該
-n
選項的 GNU 文件主要關注目標是指向目錄的符號連結的情況:'-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
(可能ln
在其他 BSD 系統上)將表現得像 GNU ,但如果目標是預先存在的連結,則會根據請求取消連結並重新創建符號連結不可訪問。即,它選擇繼續操作(標准文本允許)。ln
此外,OpenBSD 上的 GNU
ln
的行為類似於 OpenBSD 的 nativeln
,這有點有趣。刪除預先存在的符號連結
rm
不是問題,因為您似乎對其所在的目錄具有寫入和可執行權限。