介紹如何在 Linux 系統中以硬連結(hard link)共用檔案,避免重複檔案浪費磁碟空間,同時配合 ACL 管理使用者的檔案使用權限。
目錄結構
假設我們現有的目錄結構如下:
# 顯示目錄結構
tree
. ├── data │ ├── folder1 │ │ ├── test1.txt │ │ └── test2.txt │ └── folder2 │ ├── CentOS.iso │ └── qiime2.yml ├── user1 └── user2
data
為原始資料目錄,user1
與 user2
為使用者的個別目錄。在 data
目錄之下放置了所有的原始資料,而不同的使用者可以讀取的檔案都不同,例如 user1
可能可以讀取 data/folder1/test1.txt
,但是不能讀取 data/folder1/test2.txt
。
如果在檔案不多的狀況下,直接把每個使用者可以使用的檔案複製到個別的使用者目錄即可,但是如果使用者數量很多,每個檔案大小也很大的話,若每一位使用者都複製一份檔案到各自的目錄,會造成太多重複的大型檔案,浪費磁碟空間。
建立硬連結
硬連結(hard link)可以讓多個檔案路徑名稱共用同一個檔案內容,將一個檔案建立多個硬連結,配合外層目錄的權限設定,就可以讓個別使用者存取不同的檔案集,並且也不會有檔案重複儲存的問題。
硬連結的好處就是連結檔案本身跟原始檔案都是指向相同的檔案內容,使用者讀取檔案時就跟讀取原始檔案一模一樣,而且使用者無法得知原始檔案的路徑,這對於原始資料的保密很有幫助。
硬連結有一個特別的限制,就是不可以建立目錄的硬連結,因此在個別的使用者目錄中建立硬連結的時候,若需要保持跟原始資料一樣的目錄結構,就必須新建目錄結構,再將硬連結建立在其中。
建立硬連結的方式有好幾種,最基本的方式是自己建立好目錄結構,再使用 ln
指令建立硬連結:
# 建立目錄結構 mkdir -p user1/data/folder1 # 建立硬連結 ln -t user1/data/folder1 data/folder1/test1.txt # 查看檔案 ls -l user1/data/folder1/ data/folder1/
data/folder1/: total 44 -rw-r--r-- 2 ubuntu ubuntu 6538 Jan 21 06:45 test1.txt -rw-r--r-- 1 ubuntu ubuntu 35716 Feb 4 00:52 test2.txt user1/data/folder1/: total 8 -rw-r--r-- 2 ubuntu ubuntu 6538 Jan 21 06:45 test1.txt
在建立 test1.txt
的硬連結之後,其硬連結的數量就會增加,新的硬連結使用起來就跟原始檔案沒什麼差別。
若總是要保持完整的目錄結構,可以改用 cp
指令,它可以使用硬連結方式複製檔案,並保留原始的目錄結構:
# 以硬連結方式複製檔案,並保留目錄結構 cp --link --parents data/folder1/test2.txt user2/ cp --link --parents data/folder2/CentOS.iso user2/
若要將整個目錄之下的所有檔案都建立硬連結,並且保持所有子目錄結構,可以再加上 --recursive
參數。
# 對整個目錄下所有檔案建立硬連結 cp --link --parents --recursive data/folder2 user2/
這樣在建立大量的目錄結構時就會非常方便。
# 顯示目錄結構
tree
. ├── data │ ├── folder1 │ │ ├── test1.txt │ │ └── test2.txt │ └── folder2 │ ├── CentOS.iso │ └── qiime2.yml ├── user1 │ └── data │ └── folder1 │ └── test1.txt └── user2 └── data ├── folder1 │ └── test2.txt └── folder2 └── CentOS.iso
設定 ACL 權限
上面建立的硬連結只有處理重複檔案的問題而已,至於檔案權限問題必須另外以 ACL 進行設定。
首先設定原始資料目錄的權限,這部份不需要 ACL,只需要使用一般的檔案權限,將所有檔案開放可讀,然後將頂層目錄鎖住即可。
# 開啟目錄與檔案讀取權限 chmod -R og=rX data/* # 鎖住頂層目錄權限 chmod 700 data/
接著設定個別使用者的目錄權限,一樣將所有目錄與檔案設為可讀,然後將頂層目錄鎖住:
# 開啟目錄與檔案讀取權限 chmod -R og=rX user1/* user2/* # 鎖住頂層目錄權限 chmod 700 user1/ user2/
最後將每一個使用者目錄以 ACL 權限控管的方式,開放頂層目錄讀取與執行權限:
# 設定頂層目錄 ACL 權限 setfacl -m user:user1:rx user1/ setfacl -m user:user2:rx user2/
這樣就完成所有的設定了。
權限測試
檔案共享機制設定完成後,接著要測試一下權限管理是否如我們所預期,我們使用 user1
帳號登入之後,查看一下整個目錄樹:
# 顯示目錄結構(user1 使用者)
tree
. ├── data [error opening dir] ├── user1 │ └── data │ └── folder1 │ └── test1.txt └── user2 [error opening dir]
結果顯示 user1
這位使用者只能看到自己目錄下面的檔案,其餘目錄中的內容是無法讀取的。
接著測試讀取 test1.txt
這個檔案:
# 測試讀取 test1.txt 檔案
head user1/data/folder1/test1.txt
若可以看到檔案內容,就表示正常。
另外我們也可以測試一下 user1
沒有權限讀取的檔案,是否有被正確保護住:
# 測試無讀取權限的檔案
head user2/data/folder1/test2.txt
head: cannot open 'user2/data/folder1/test2.txt' for reading: Permission denied
# 測試無讀取權限的檔案
head data/folder1/test2.txt
head: cannot open 'data/folder1/test2.txt' for reading: Permission denied
正常來說,user1
只能讀取自己目錄下的檔案,其他使用者或是原始資料目錄下的任何檔案或目錄都無法讀取,就算它知道完整的檔案路徑,也是無法看到內容的,這樣就完美解決權限控管以及磁碟儲存空間的問題了。