NFS 檔案分享

author:Yung-Yu Chen (yungyuc) http://blog.seety.org/everydaywork/ <yyc@seety.org>
copyright:© 2006, all rights reserved

目錄

1   NFS 的用途

NFS 是 Network File System (網路檔案系統) 的縮寫。在 2.6 版的 Linux 核心裡已經包含了 NFS 掛載使用與伺服的功能;Debian 預設的核心版本 (kernel-image) 也是開啟的 (compiled-in)。

NFS 為網路系統管理人員提供了網路檔案共享的方便機制。透過 NFS,主機可以「匯出」本地的磁碟為共享的網路磁碟,而其它被接受的客戶端則能夠使用這些共享磁碟上的檔案資源;NFS 客戶端可以和像一般磁碟一樣掛載這些網路磁碟,對其中的檔案執行輸出入、改變權限等等各種操作。NFS 網路檔案系統所提供的輸出入功能與本地磁碟仍有差異,譬如沒有辦法建立 memory-mapped 檔案,但基本上在大部分的使用狀況下都可以被視為與本地檔案系統同等的存在。NFS 網路磁碟系統最極端的應用就是無磁碟工作站;這種無磁碟工作站主機可以不需要任何本地的儲存裝置,完全透過 NFS 來存放執行所需的檔案資料。

除了無磁碟工作站這種極端 (但很有用!) 的案例不談,NFS 廣泛使用在以下的環境裡:

2   掛載 NFS

經過長時間的演進與修改,Linux 已經把 NFS 的伺服與客戶端程式整合到核心裡面了。如果我們想要使用其它 NFS 伺服器提供的匯出共享,直接使用標準的基本 mount 工具程式進行掛載的動作即可:

$ mount hostname:/export/path /mount/point

掛載的語法是:

mount <file system> <mount point>

如果更仔細一點的話,我們應該加上指定掛載型態 (為 NFS) 的參數:

$ mount -t nfs hostname:/export/path /mount/point

只不過因為我們的 <file system> 用了 NFS 的語法,``mount`` 程式夠聰明,知道要用 nfs 型態來掛載,就可以省略 -t nfs

指令行的寫法如上,如果要把掛載動作寫進 fstab 裡的話,語法如下:

<file system> <mount point> <type> <options> <dump> <pass>

一樣,<file system> 是要被掛載的網路分享;``<mount point>`` 是本地的掛載點。這裡的 <type> 不能省略,一定要寫成 nfs,而 <options> 寫成 defaults 就可以留為預設值 (如同直接用 mount 不加 -o 指定參數)。NFS 掛載的 <dump> 一般設為 0,不必傾印;因為我們不會對 NFS 作 fsck (磁碟檢查),所以設定檢查順序的 <pass> 參數並不重要,設 0 即可。

3   伺服端設定

在 Debian 下有兩種 NFS 伺服程式:nfs-kernel-servernfs-user-server。一般我們會安裝 kernel server;user server 功能雖然比較多,但速度慢、穩定性比較差。除非有特別的需要,否則應該用 kernel server。

套件安裝好了以後,可以用

$ /etc/init.d/nfs-kernel-server start

來啟動伺服器;通常套件在安裝完畢之後自己就會啟動。我們可以用 exportfs 工具來檢視本機所分享出來的 NFS,在剛裝好 NFS 伺服器的現在,應該不會印出任何訊息;也就是沒有分享。

NFS 的分享設定檔寫在 /etc/exports,裡面的每一行代表一個分享,語法如下:

<export/share point> <client list>

前面是本機要分享出去的目錄;後面是允許連線的客戶端位址。兩者間以空白分隔,而 <client list> 可以列出一組以上的客戶端位址,也以空白分隔。以 # 開頭的文字代表註解,並不生效。

NFS 伺服器的 <export point> 會把本機檔案系統分享出去;譬如我們要分享 /var/local/data 目錄,其它的客戶端就會看到這個目錄。這textbf{和 Windows 的資源分享不一樣},不能指定分享出去的名稱。來舉個例子看看:

/usr    node*(rw,sync,no_root_squash)
/home   node*(rw,sync,no_root_squash)

這三行設定指定分享 /usr/home 目錄給所有以 node 開頭的主機,並且設定 rw,sync,no_root_squash 選項。客戶端列表可以使用萬用字元,而有多組客戶端並以空白分隔時,每組均需在括號中寫明 NFS 選項 (不寫表示使用預設值)。

在表列客戶端的時候可以用 IP 或是主機名稱;主機名稱的來源可以是 hosts 檔案或 DNS 反查 (如果使用 DNS 反查,就要確定反查的來源是可靠的)。``192.168.101.*`` 或 *.myhost.com, cluster* 等都是有效的客戶端名稱。然而,在用主機名稱進行指定的時候,萬用字元寫作前飾詞比寫作後飾詞要來得安全,比較可以避免讓未經授權的主機透過外部 DNS 反查而意外獲得權限的機會。用 IP 指定的話比較不會有這個狀況發生。

一般我們常用的 NFS 選項有:

設定好了以後,我們執行

$ /etc/init.d/nfs-kernel-server restart

重新啟動 NFS 伺服器,或是用

$ exportfs -rv

指示 NFS 伺服器重新讀取 /etc/exports 進行分享1

[1]nfs-kernel-server reload 也會呼叫 exportfs -r 進行重新分享。

showmount -e 可以檢視任何一台主機的 NFS 分享:

$ showmount myhost -e
Export list for myhost:
/home myhost.*(rw,wdelay,root_squash)

它會實際與 NFS 伺服器連線,所以可以用來檢查我們的組態是否正確。如果一切都如我們的預期,基本的 NFS 伺服器組態就算是完成了。關於更進一步的資訊,請參考 exports (5), exportfs (8)showmount (8)

4   客戶端設定

使用 NFS 的客戶端直接照一般的方式掛載檔案系統即可,以下列出常用的 NFS 掛載選項:

詳細的設定選項請參考 nfs (5)mount (8)

5   關於檔案權限的注意事項

NFS 伺服器在分享目錄出來的時候,一般來說會把檔案系統的權限結構一起分享出來。也就是說,在 NFS 伺服器上屬於 UID 1003 的檔案,也同時屬於客戶端電腦上 UID 1003 的使用者。如果我們要分享的是伺服器上的 /home,那麼這正是我們想要的結果;但若我們想要分享的是一些資料,譬如 /var/local/gallery 裡的圖檔,提供給美工人員使用,那可能就不希望它們屬於任何一個使用者。

為了避免預期之外的效果,通常我們會把 NFS 用在帳號組態均勻的環境裡面 footnote{通常是一群用 NIS 或 LDAP 等服務作過帳號整合的主機。},這樣的環境包括 Linux 叢集、工作群組等。不過,如果一定要在帳號組態完全不同的環境下使用 NFS 的話,該怎麼辦呢?

NFS 伺服器提供了 "squash" 的功能,用來解決 UID 對應的問題。我們在前面組態伺服器的地方看到了 root_squash 這個選項,它的功能是把客戶端超級使用者的 UID/GID 對應成匿名使用者,這樣客戶端的超級使用者就改不了伺服端的資料了。同樣地,NFS 伺服器還有一個 all_squash 選項,會把textbf{所有}使用者的 UID/GID 對應到匿名使用者;通常,我們還會用 anonuid=anongid= 這兩個選項來指定匿名使用者的 UID/GID。

"all squash" 過之後,客戶端在存取 NFS 伺服器資料的時候就不再是用自己的身份,而是用 "squash" 過的匿名使用者身份來存取資料。一般不限定客戶端身份或是公開的 NFS 分享,一定會用這種或類似的模式進行設定 footnote{近來已經比較少有人提供公開的 NFS 服務了,多半都改用 FTP 或 HTTP;也有一些單位改提供公開的 smb 分享 (利用 Samba)。}。

如果我們希望用更具彈性、可由使用者操控的方式來進行網路檔案分享,應該要考慮改用 Samba。NFS 的權限架構在本質上是給主機管理員使用的,適合在系統層級提供檔案共享服務。

6   結語

如果我們要管理的是一整群主機,就會發現用 NFS 來共享主機上的資料可以帶來非常大的方便性。光只是把主要主機的 /home 分享給次要主機使用,就可以省下許多資料同步的困擾。

然而,NFS 是設計在系統管理員層級的服務,一般使用者用起來並不方便。我們還有 SMBFS 這種利用 SMB/CIFS 協定來通訊的網路檔案系統可以利用,請參考 Debian smbfs 套件的說明及相關 manpage 以獲得更多資訊。