开始使用 NFS 共享文件

作者:Olexiy Tykhomyrov

如果您有两台或多台机器,您可能希望在机器之间共享磁盘空间或设备,例如 CD 驱动器。为此,有网络文件系统 (NFS),这是跨网络共享文件和资源的最简单方法。

NFS 是在远程机器上处理文件的方式,就好像它们在您的本地机器上一样。NFS 是从网络上任何机器访问相同 $HOME 目录的标准事实解决方案。使用它也是避免重复信息占用大量磁盘空间的好方法。

NFS 最初是由 Sun Microsystems 的工程师于 1985 年推出的。NFS 非常古老,但仍然很好,并且不断改进。Sun 正在致力于为 Linux 生产 NFS 版本 4 的实现,目前正处于开发阶段。

Linux 的标准 NFS 版本是 3。本文讨论的是这个版本。从普通用户的角度来看,版本之间只有很少的区别。

在客户端和服务器端安装 NFS 都不难。我们将展示一些基本的 NFS 功能并解释它们的用途。许多命令必须以 root 身份执行,所以在按 Enter 键之前请三思。

但首先,NFS 是如何工作的。NFS 是最著名的使用远程过程调用 (RPC) 的服务。例如,假设一台名为 tiger 的服务器机器将所有 $HOME 文件保存在目录 /home 中。从您的本地机器(名为 blackcat)上,您将发出命令

mount -t nfs tiger:/home /home

根据此命令,mount 将尝试通过 RPC 连接到服务器 tiger 上的 rpc.mountd 守护程序。服务器将检查是否允许从 blackcat 挂载 /home,并返回一个文件句柄,该句柄可以用来服务于 /home 下的所有文件请求。如果请求不被允许,我们将看到相应的诊断消息。请注意,命令中的冒号表示文件系统是远程的,因此可以省略 -t nfs。让我们想象一下文件句柄已成功返回,并且我们正在与一台友好的 tiger 打交道。

当 blackcat 上的用户尝试访问 NFS 上的文件时,内核会向 NFS 守护程序(通常是 rpc.nfsd)发出 RPC 调用,并将文件名、用户和组 ID(uid 和 gid)作为参数传递。因此,服务器 tiger 可以在发送文件句柄之前阻止未经授权的访问。挂载过程如图 1 所示。

Starting Share Files with NFS

图 1. 挂载过程

设置 NFS 服务器

如果您想让您的 Linux 机器充当 NFS 服务器,您必须在那里运行 rpc.mountd 程序。此程序有助于挂载阶段,并将挂载 NFS 请求传递给 rpc.nfsd 程序,后者几乎完成所有工作并充当 NFS 服务器。RPC 协议还定义了使用服务机器上内核的性能统计信息,这反过来有助于与 rpc.lockd 和 rpc.rquotad 一起工作。自从内核 2.2.18 以来,rpc.lockd 由 rpc.nfsd 在请求时调用,因此可能不需要手动启动。必须启动 rpc.rquotad 程序才能使配额服务在 NFS 上工作。

正如您所记得的,我们提到了 RPC。这意味着对于 NFS 连接,我们不需要更改控制互联网超级服务器 inetd 的程序的 /etc/inetd.config。NFS 使用另一个程序 portmapper,它显示了查找系统上所有 NFS 服务的方法。

保护您的机器免受永久网络请求的第一道防线使用一对文件 /etc/hosts.allow 和 /etc/hosts.deny,以允许请求被处理或拒绝。此防线识别两件事:请求的类型和发送请求的主机。然后它查看文件 hosts.allow 以查找这些参数。如果找到,请求将通过。如果未找到,防线会查看 /etc/hosts.deny,如果这对参数匹配,则拒绝查询。如果这对参数与 /etc/hosts.allow 或 /etc/hosts.deny 都不匹配,则请求将通过。

如果您正在为例如教育机构设置服务器,您必须更加注意安全性。在任何这样的机构中,例如,都有“第五纵队”,通常来自学生:一部分人在嗅探您的密码和其他敏感信息,第二部分人在发送“我爱你”电子邮件,第三部分人在用特洛伊木马礼物送给您。NFS,尤其是其旧版本,具有一组潜在的安全级别较低的功能。因此,最好正确设置这些文件。

要了解有关这些文件的更多信息,请查阅 man page 第五节中的 hosts_access。但是,通常只需禁止所有机器访问 portmapper 和其他 NFS 请求,并允许特定主机或子网的需求就足够了。因此,在文件 /etc/hosts.deny 中,您需要放入以下行

portmap:ALL
lockd:ALL
mountd:ALL
rquotad:ALL
statd:ALL

执行此操作后,没有人可以访问您的 NFS 服务器,当然这不是我们需要的,所以让我们也更改 /etc/hosts.allow 文件。文件中行的通用格式如下所示

daemon list : ... user pattern@host pattern
例如,为了允许 IP 地址分别为 192.168.16.13 和 192.168.16.24 的机器 blackcat 和 tomcat 使用 NFS,我们必须为我们禁用的所有服务在 /etc/hosts.allow 文件中添加相应的行
portmap : 192.168.16.13  192.168.16.24
lockd   : 192.168.16.13  192.168.16.24
mountd  : 192.168.16.13  192.168.16.24
rquotad : 192.168.16.13  192.168.16.24
statd   : 192.168.16.13  192.168.16.24
如果您正在使用 NFS 连接,并且客户端通常占用连续的子网,因此地址范围对应,则允许主机的行可能太长。为了简化,还有另一种方法可以指向这样的客户端集:在这种情况下,使用 address/netmask,因为它使文件更短更易读。例如,192.168.16.0/255.255.255 匹配 192.168.16.0 到 192.168.16.255 范围内的所有 IP 地址。

到目前为止,我们只提到了适用于许多网络服务的通用功能。NFS 服务的配置文件 /etc/exports 更具体。在猫科动物家族的这两台机器 blackcat 和 tomcat 上,通过 NFS 挂载 /home 和 /usr/doc 目录

/home    192.168.16.11(rw,root squash)
192.168.16.24(rw)
/usr/doc 192.168.16.11(ro,root squash)
192.168.16.24(ro)

格式很简洁;在左侧字段中,我们放入要导出的目录名称,然后枚举对 host(权限)。注意:IP 地址后没有空格。在上面的示例中,我们可以在 /home 中写入和读取,并且只能读取 /usr/doc 和子目录。参数 root_squash 是为了保护文件免受客户端 root 访问。这意味着用户(例如,学生)在成功破解客户端 root 密码后,可能成为 root 用户,但仍然无法访问或更改只有服务器上的 root 用户才能访问的文件。这很好,并且该选项默认设置。squash 这个词意味着 root 用户将具有与用户 nobody 相同的访问权限。

如果我们仔细观察 root 的情况,我们也会推断出我们应该对用户和组识别号做些什么:uid 和 gid。如果用户在客户端和服务器上具有不同的 uid 和 gid,则用户可能无法完全访问他或她自己的文件,但可以访问属于另一个用户的文件。

为了避免这种情况,您可以设置文件以指示 uid/gid 的静态映射。在下面的示例中,该选项指向文件 /etc/nfs/home_map.cats,它可能如下所示

map_static=/etc/nfs/home map.cats

用于映射的文件 home_map.cats 可能如下所示

# Mapping for cat's machines:
#    server    client
uid   0-60       -    # switch to nobody
uid   61-80     41    # map 61-80 into 41-60
服务器和客户端上的守护程序之间的通信过程如图 2 所示。
Starting Share Files with NFS

图 2. 守护程序之间的通信

如果您运行的是 NIS 系统,则 NFS 服务器可以使用它来查询 uid/gid。在这种情况下,您应该使用另一个选项 map_nis=kingdom.cat。此解决方案更智能;NFS 服务器将从 NIS 域 kingdom.cat 获取相应的信息。

要允许在您的 NIS 系统中描述的一组受信任用户进行挂载过程,您可以使用参数 @group。如果您放入例如 @catowners,则只会提取组 catowners 的所有成员的主机部分以添加到访问列表。

正确安装这些文件后,您应该启动相应的程序。由于 NFS 使用 portmapper,因此应首先运行 portmapper。在最新版本的 Linux 发行版中,portmap 或 rpc.portmap 在系统启动时启动。您可以通过在一行中发出以下两个命令来检查程序的当前状态

ps axu | egrep portmap

如果 portmap 正在运行,您将看到类似这样的内容

daemon 99    0.0 0.3 1132 500 ?     S Jul11 0:02
/sbin/portmap
tiger  27837 0.0 0.3 1264 492 pts/0 R 17:03 0:00
egrep portmap
这里的第一行通知 portmap 正在运行。如果 portmapper 未运行,您应该尝试手动运行它。该程序通常位于 /sbin 中,但如果没有,请尝试 /usr/sbin。如果该程序不可用,您必须安装它。要安装的软件包的名称可能类似于 netbase 或 nkitb。

运行 portmapper 后,您可以启动所需的守护程序:rpc.mountd、rpc.nfsd、rpc.statd、rpc.lockd 和 rpc.quotad。这些守护程序必须完全按照此顺序启动。现代发行版(我们检查过 Debian 2.2r3、Red Hat 7.1 和 SuSE 7.0)具有这些服务的启动/停止脚本。如果您在查找此类脚本时遇到问题,您可以从 SuSE 或 Red Hat 发行版中获取现成的脚本并手动更正,或者编写您自己的脚本。

一般来说,只有当您使用配额系统来限制用户的磁盘空间时才需要 rpc.rquotad。在最新版本的内核中,rpc.lockd 由 rpc.nfsd 在请求时调用,但从脚本启动它也可以。

在启动所有这些程序后,执行命令 rpcinfo -p。此命令的输出显示当前正在运行的程序、它们的版本和其他有用的信息。至少 portmapper、mountd 和 nfsd 必须正在运行才能使您能够使用 NFS 服务器。如果您有任何问题,您可以在 Linux NFS-HOWTO 文档中找到帮助。

设置 NFS 客户端

首先,确保您的 Linux 内核支持 NFS。您的系统的状态由 proc 目录反映。要查看 filesystems 文件内部,请执行 cat 命令,如下所示

tomcat> cat /proc/filesystems
         ext2
nodev    proc
nodev    devpts
         iso9660
nodev    nfs

此文件显示您可以在内核版本中使用的文件系统类型。如果缺少行 nodev nfs,则可能意味着您的 NFS 文件系统支持模块未安装。在这种情况下,请尝试执行命令 modpobe nfs。您必须是 root 用户才能执行它。命令的输出描绘了情况。如果模块已编译,则该命令会安装它,如果您重复 cat 命令,将显示线索行。如果您的内核不支持 NFS 服务器,您可能必须重新编译它,但此主题远远超出了本文的范围。

如果您支持 NFS,您可以挂载位于服务器机器上的文件,正如我们在示例中所示。mount 命令的完整格式如下

mount -t nfs server:exp dir local dir options

此处 server 是您的 NFS 服务器的名称,exp_dir 是服务器机器上要导出的目录的完整路径。

通常这就是故事的结局,但为了最大限度地提高通过 NFS 连接的生产力,让我们看看选项参数。我们肯定会在以后使用它们

  • rsize=n 和 wsize=n:分别指定 NFS 客户端在读取和写入请求时发送或接受的数据报的大小。默认值取决于内核的版本,可以设置为 1,024 字节。您的猫一次可以吃掉的食物块越大,它吃完食物的速度就越快。因此,您在此处放置的值越大,您使用远程文件的速度就越快。如果您在此处放置 4,096 甚至 8,192,吞吐量可能会大大提高。

  • timeo=n 和 retrans=n:回答对 RPC 超时的反应。如果您的宠物(以猫为例)吃了很多东西,它可以在消化一小段时间后吃掉一小块新食物,并在很长一段时间后再次吃很多东西。这些时间间隔分别称为次要和主要。虽然 NFS 不是猫,但它也有次要和主要时间间隔,与服务器的反应有关。网络或服务器,甚至两者,都可能暂时关闭或无法访问。如果发生这种情况,重发将在 timeo 十分之一秒后开始。此小超时的标准值为 7。因此,如果在 0.7 秒内没有回复,NFS 客户端将重复相同的请求并将超时时间加倍(默认为 1.4 秒)。如果仍然没有回复,则将重复该过程,直到达到 60 秒的最大主要超时时间。在达到主要超时时间之前必须发生的小超时次数由 retrans 参数设置;其默认值为 3。

  • hard 和 soft:定义达到主要超时时间时的反应。在第一种情况下,如果设置了默认值 hard,NFS 客户端会在控制台上报告错误“服务器未响应,仍在尝试”,并继续尝试连接。因此,当 NFS 服务器恢复在线时,程序将从中断的地方继续运行。相反,如果设置了值 soft,NFS 客户端将向访问 NFS 挂载文件系统上的文件的进程报告 I/O 错误,并且某些文件可能会因数据丢失而损坏,因此请谨慎使用 soft 选项。

  • intr:允许中断 NFS 调用,如果服务器长时间没有响应,则对于取消作业很有用。

推荐的选项是 intr 和 hard,由于后者是默认值,因此 intr 就足够了。使用这些参数,我们能够尝试提高 NFS 连接的性能。

通常,我们希望以隐藏方式(透明地)执行挂载过程,可能在启动系统时。在这种情况下,我们必须在系统启动时读取的名为 /etc/fstab 的文件中创建相应的行。该文件中的任何行至少有四个字段,通常是六个字段。这是一个例子

1)device 2)mnt point 3)fs type 4)options
5)dump 6)check order
tiger:/nfs1/home /home nfs rw,hard,intr 0 2

第一个参数描述要挂载的设备。在此示例中,NFS 服务器 tiger 将 /nfs1/home 文件系统导出为 home 目录。字段编号四将此文件系统指向 nfs。最后一个参数表示文件系统不应被转储并在二级中检查。您可以在手册页的第五节中找到更多详细信息。启动 rpc.lockd 和 rpc.statd 也是一个好主意。这些程序通常从脚本初始化。完成这些操作后,您应该就可以运行 NFS 客户端了。

计划使用 NFS

我们可以将哪种类型的数据保存在 NFS 上?最简单的答案是任何类型,包括无盘机器的整个根系统。为了规划您的系统,您必须考虑到所有文件都可以分为两类:可共享数据和不可共享数据。后者必须保存在特定的机器上。例如,设备(和锁)文件是不可共享的。某些目录的大小对于某些人来说是稳定的,而对于另一些人来说是不稳定的。

假设我们有一个小型系统,我们将 /home 显示为典型的可共享数据,应该位于服务器主机上。在中小型的系统上,按用户组细分用户主目录很有用,例如使用 /home/students 等名称。$HOME 目录的大小当然不是静态的,但是为了限制许多人的磁盘空间,您可以在服务器上设置配额系统。

其他目录呢?有些目录的大小是静态的,有些目录则永久更改。可共享的静态目录包括 /usr 和 /opt,而不可共享的静态目录包括 /etc 和 /boot。静态可变目录包括 /var/mail 和 /var/spool/news,而不可共享的可变目录包括 /var/run 和 /var/lock。

许多人由于速度原因而不将 /usr/bin 和 /bin 文件放在 NFS 上,但这不是很关键。我们相信普通用户不会注意到从 NFS 目录调用程序与从本地目录调用程序有任何区别。因此,如果磁盘空间至关重要,您可以主要通过 NFS 挂载所有内容,从服务器机器导入文件,同时在客户端机器上保留空间用于其他文件,例如 MP3 或两个操作系统。

虽然您可以将所有内容都保存在服务器上,但标准解决方案是仅将 $HOME 目录和文档保存在那里,包括手册页和其他文档。通过 NFS 共享很少使用的软件,这些软件通常位于 /opt 和 /usr/local 下,也是一个非常好的主意。应通过 NFS 共享两个子目录:/usr/doc 和 /usr/share。

现在,在这种情况下我们如何使用挂载参数?如前所述,$HOME 的推荐选项是 intr 和 hard。在这种情况下,您可以确保数据不会丢失。但是,对于 /usr/doc 和类似的子目录,这可能不是最佳选择。如果在网络过载时访问手册页,或者即使 NFS 服务器关闭,您的机器也会等待,直到它能够重新建立与 NFS 服务器的联系。在这种情况下,使用 soft 选项更好;断开连接消息将出现在屏幕上,并且操作将被取消。此选项可能对任何类型的非关键数据(包括新闻和 FTP 目录)都很有用。但是,标准选择是不通过 NFS 访问 /var/mail 和 /var/news;使用 imap、pop 和 nntp 等特殊协议。

改进 NFS 连接

如果您担心 NFS 连接的速度,您也可以使用 rsize 和 wsize 选项。默认大小由内核设置,可能适合也可能不适合。例如,您的以太网卡或内核无法处理大块数据,这种情况通常发生在旧硬件和旧内核上。如果您有更新的网卡,更大的尺寸可能有助于您获得更好的性能。在某些情况下,您可以将速度提高五倍或更多倍,但您必须对您的网络进行一些实验。

计算速度的最简单方法是创建一个位于 NFS 卷上的文件,并找到创建的时间。这只是一个实验性文件,可以保存任何类型的数据,包括零序列,因此我们将通过 dd 命令使用 /dev/zero 作为源文件来创建它。命令 time 计算创建时间。

临时文件应该有多大?规则是服务器机器上内存大小的两到三倍。如果您在那里有 2MB 的 RAM,则文件应为 4MB。有时很难找到这样一个文件的位置,但在许多情况下,NFS 磁盘机器上的 256MB 应该足够好。要计算磁盘上的可用区域,请使用命令 df。然后,假设您正在客户端机器上工作,卸载并重新挂载它,将 rsize 和 wsize 参数的魔术值设置为 1,024。然后执行带时间的 dd 命令

time dd if=/dev/zero of=/home/tempo bs=16k count=16384

我们使用 /dev/zero 作为 /home/tempo 的源,以避免计算读取源的时间。此命令发送 16,384 个 16KB 的空字节块,创建一个总大小为 16,000 字节 × 16,384/1024 千字节 = 256 千字节或 256MB 的文件。记下时间。然后计算读取时间,将文件发送到 /dev/null

time dd if=/home/tempo of=/dev/null bs=16k
记录读取时间,然后删除临时文件
rm /home/tempo verbatim
至少重复三次描述的过程,并计算平均读取/写入时间。卸载您的客户端主机
umount /home verbatim
确保您已卸载 NFS;如果出现错误,它会抱怨,如果没有错误,则保持沉默。然后再次挂载它,为 rsize 和 wsize 使用新值 2,048,并再次重复上述过程,直到 32,768。

观察结果。传输速度越快,时间越短。找到您的最佳值并将其放入 /ets/fstab 中。将带有计算结果的纸张保存在安全的地方。

还有一些技巧可以帮助您缩短此列表。如果您有一个新的网卡并且确信您的 NFS 服务器运行的是版本 3,您可以从值 32,768 开始并向下调整。但是,此值不应在 NFS 服务器版本 2 上进行测试,因为它仅适用于旧内核和某些 Solaris 和 SunOS 机器。

我们发现内核 2.2.19 的最佳结果是值 4,096,因此您可以从此值开始并尝试最接近的值 2,048 和 8,192。对于新内核,此值(在我们的例子中)为 8,192,但通常内核 2.2.19 比 2.4.6 工作得更好。这在很大程度上取决于您的硬件,因此如果您想将 NFS 服务器切换到新的内核版本,请务必小心。

对于通过 TCP/IP 使用 NFS 的客户端机器,最佳值为 1,024 或更小。如果您在客户端和 NFS 服务器之间有路由器,此值也适用。

关于 NFS 版本

当 NFS 文件系统的挂载命令正在工作时,协议的版本将被识别,并且屏幕上可能会出现警告消息。通常,它表示服务器的 NFS 版本比内核机制旧。

通过网络共享文件的想法与网络本身一样古老,因此存在并发解决方案列表。为了改进 NFS,请尝试版本 4 或简称 NFSv4,它是在 2000 年推出的。NFS 的发明者 Sun Microsystems 是 Linux NFSv4 项目的赞助商。它当然具有以前版本的所有功能,但通过扩展基本的 RPC 安全机制来支持安全性,因此解决了以前版本的最薄弱环节。另一个薄弱环节,缺乏国际化,也不再存在。由于缓存,传输速度得到了提高。我们也可以避免计算最佳参数的那些过程,因为支持了改进访问的新机制。将此版本付诸实践意味着无需灰尘和噪音——如今 Linux NFSv3 服务器支持文件锁定——NFSv4 功能。

所以,不要忘记网络上的老藤蔓 NFS。它仍然不是历史的醋。

资源

Starting Share Files with NFS
Olexiy Tykhomyrov (tiger@ff.dsu.dp.ua) 自 1994 年以来一直在使用 Linux。他在第聂伯罗彼得罗夫斯克国立大学实验物理系工作,教授物理和通信。他爱他的儿子米沙,米沙叫他老虎,因为他的一些学生害怕他。老虎喜欢游泳和旅行。

Starting Share Files with NFS
Denis Tonkonog,老虎的前学生,在同一地点工作,也喜欢旅行和持枪钓鱼。朋友们叫他黑猫,但没人知道为什么。可以通过电子邮件 denis@ff.dsu.dp.ua 联系到他
加载 Disqus 评论