30.3. 网络文件系统(NFS)

Reorganized and enhanced by Tom Rhodes.
Written by Bill Swingle.

网络文件系统是FreeBSD支持的文件系统中的一种, 也被称为 NFSNFS允许一个系统在网络上与它人共享目录和文件。通过使用NFS,用户和程序可以象访问本地文件 一样访问远端系统上的文件。

以下是NFS最显而易见的好处:

30.3.1. NFS是如何工作的

NFS 至少包括两个主要的部分: 一台服务器, 以及至少一台客户机, 客户机远程地访问保存在服务器上的数据。 要让这一切运转起来, 需要配置并运行几个程序。

服务器必须运行以下服务:

服务描述
nfsdNFS,为来自NFS客户端的 请求服务。
mountdNFS挂载服务,处理nfsd(8)递交过来的请求。
rpcbind 此服务允许 NFS 客户程序查询正在被 NFS 服务使用的端口。

客户端同样运行一些进程,比如 nfsiodnfsiod处理来自NFS的请求。 这是可选的,而且可以提高性能,对于普通和正确的操作来说并不是必须的。 参考nfsiod(8)手册获得更多信息。

30.3.2. 配置NFS

NFS的配置过程相对简单。这个过程只需要 对/etc/rc.conf文件作一些简单修改。

NFS服务器这端,确认/etc/rc.conf 文件里头以下开关都配上了:

rpcbind_enable="YES"nfs_server_enable="YES"mountd_flags="-r"

只要NFS服务被置为enable,mountd 就能自动运行。

在客户端一侧,确认下面这个开关出现在 /etc/rc.conf里头:

nfs_client_enable="YES"

/etc/exports文件指定了哪个文件系统 NFS应该输出(有时被称为共享)。 /etc/exports里面每行指定一个输出的文件系统和 哪些机器可以访问该文件系统。在指定机器访问权限的同时,访问选项 开关也可以被指定。有很多开关可以被用在这个文件里头,不过不会在这 里详细谈。您可以通过阅读exports(5) 手册来发现这些开关。

以下是一些/etc/exports的例子:

下面是一个输出文件系统的例子, 不过这种配置与您所处的网络环境及其配置密切相关。 例如, 如果要把 /cdrom 输出给与服务器域名相同的三台计算机 (因此例子中只有机器名, 而没有给出这些计算机的域名), 或在 /etc/hosts 文件中进行了这种配置。 -ro 标志表示把输出的文件系统置为只读。 由于使用了这个标志, 远程系统在输出的文件系统上就不能写入任何变动了。

/cdrom -ro host1 host2 host3

下面的例子可以输出/home给三个以IP地址方式表示的主机。 对于在没有配置DNS服务器的私有网络里头,这很有用。 此外, /etc/hosts 文件也可以用以配置主机名;参看 hosts(5)-alldirs 标记允许子目录被作为挂载点。 也就是说,客户端可以根据需要挂载需要的目录。

/home -alldirs 10.0.0.2 10.0.0.3 10.0.0.4

下面几行输出 /a ,以便两个来自不同域的客户端可以访问文件系统。 -maproot=root 标记授权远端系统上的 root 用户在被输出的文件系统上以root身份进行读写。 如果没有特别指定 -maproot=root 标记, 则即使用户在远端系统上是 root 身份, 也不能修改被输出文件系统上的文件。

/a -maproot=root host.example.com box.example.org

为了能够访问到被输出的文件系统,客户端必须被授权。 请确认客户端在您的 /etc/exports 被列出。

/etc/exports 里头,每一行里面,输出信息和文件系统一一对应。 一个远程主机每次只能对应一个文件系统。而且只能有一个默认入口。比如,假设 /usr 是独立的文件系统。这个 /etc/exports 就是无效的:

# Invalid when /usr is one file system/usr/src client/usr/ports client

一个文件系统,/usr, 有两行指定输出到同一主机, client. 解决这一问题的正确的格式是:

/usr/src /usr/ports client

在同一文件系统中, 输出到指定客户机的所有目录, 都必须写到同一行上。 没有指定客户机的行会被认为是单一主机。 这限制了你可以怎样输出的文件系统, 但对绝大多数人来说这不是问题。

下面是一个有效输出列表的例子, /usr/exports 是本地文件系统:

# Export src and ports to client01 and client02, but only# client01 has root privileges on it/usr/src /usr/ports -maproot=root client01/usr/src /usr/ports client02# The client machines have root and can mount anywhere# on /exports. Anyone in the world can mount /exports/obj read-only/exports -alldirs -maproot=root client01 client02/exports/obj -ro

在修改了 /etc/exports 文件之后, 就必须让 mountd 服务重新检查它, 以便使修改生效。 一种方法是通过给正在运行的服务程序发送 HUP 信号来完成:

# kill -HUP `cat /var/run/mountd.pid`

或指定适当的参数来运行 mountd rc(8) 脚本:

# /etc/rc.d/mountd onereload

关于使用 rc 脚本的细节, 请参见 第 12.7 节 “在 FreeBSD 中使用 rc”

另外, 系统重启动可以让 FreeBSD 把一切都弄好。 尽管如此, 重启不是必须的。 以 root 身份执行下面的命令可以搞定一切。

NFS 服务器端:

# rpcbind# nfsd -u -t -n 4# mountd -r

NFS 客户端:

# nfsiod -n 4

现在每件事情都应该就绪,以备挂载一个远端文件系统。 在这些例子里头, 服务器名字将是:server ,而客户端的名字将是: client。 如果您只打算临时挂载一个远端文件系统或者只是打算作测试配置正确与否, 只要在客户端以 root 身份执行下面的命令:

# mount server:/home /mnt

这条命令会把服务端的 /home 目录挂载到客户端的 /mnt 上。 如果配置正确,您应该可以进入客户端的 /mnt 目录并且看到所有服务端的文件。

如果您打算让系统每次在重启动的时候都自动挂载远端的文件系统,把那个文件系统加到 /etc/fstab 文件里头去。下面是例子:

server:/home /mnt nfs rw 0 0

fstab(5) 手册里有所有可用的开关。

30.3.3. 锁

某些应用程序 (例如 mutt) 需要文件上锁支持才能正常运行。 在使用 NFS 时, 可以用 rpc.lockd 来支持文件上锁功能。 要启用它, 需要在服务器和客户机的 /etc/rc.conf 中加入 (假定两端均已配好了 NFS):

rpc_lockd_enable="YES"rpc_statd_enable="YES"

然后使用下述命令启动该程序:

# /etc/rc.d/lockd start# /etc/rc.d/statd start

如果并不需要真的在 NFS 客户机和 NFS 服务器间确保上锁的语义, 可以让 NFS 客户机在本地上锁, 方法是使用 mount_nfs(8) 时指定 -L 参数。 请参见 mount_nfs(8) 联机手册以了解更多细节。

30.3.4. 实际应用

NFS 有很多实际应用。下面是比较常见的一些:

  • 多个机器共享一台CDROM或者其他设备。这对于在多台机器中安装软件来说更加便宜跟方便。

  • 在大型网络中,配置一台中心 NFS 服务器用来放置所有用户的home目录可能会带来便利。 这些目录能被输出到网络以便用户不管在哪台工作站上登录,总能得到相同的home目录。

  • 几台机器可以有通用的/usr/ports/distfiles 目录。 这样的话,当您需要在几台机器上安装port时,您可以无需在每台设备上下载而快速访问源码。

30.3.5. 通过 amd 自动地挂接

Contributed by Wylie Stilwell.
Rewritten by Chern Lee.

amd(8) (自动挂接服务) 能够自动地在访问时挂接远程的文件系统。 如果文件系统在一段时间之内没有活动, 则会被 amd 自动卸下。 通过使用 amd, 能够提供一个持久挂接以外的选择, 而后者往往需要列入 /etc/fstab

amd 通过将自己以 NFS 服务器的形式, 附加到 /host/net 目录上来工作。 当访问这些目录中的文件时, amd 将查找相应的远程挂接点, 并自动地挂接。 /net 用于挂接远程 IP 地址上导出的文件系统, 而 /host 则用于挂接远程主机名上的文件系统。

访问 /host/foobar/usr 中的文件, 相当于告诉 amd 尝试挂接在主机 foobar 上导出的 /usr

例 30.2. 通过 amd 来挂接导出的文件系统

您可以通过使用 showmount 命令来查看远程主机上导出的文件系统。 例如, 要查看 foobar 上导出的文件系统, 可以用:

% showmount -e foobarExports list on foobar:/usr 10.10.10.0/a 10.10.10.0% cd /host/foobar/usr

如同在前面例子中所看到的, showmount 显示了导出的 /usr。 当进入 /host/foobar/usr 这个目录时, amd 将尝试解析主机名 foobar 并自动地挂接需要的文件系统导出。

amd 可以通过启动脚本来启动, 方法是在 /etc/rc.conf 中加入:

amd_enable="YES"

除此之外, 还可以给 amd 通过 amd_flags 选项来传递额外的参数。 默认情况下, amd_flags 为:

amd_flags="-a /.amd_mnt -l syslog /host /etc/amd.map /net /etc/amd.map"

/etc/amd.map 文件定义了挂接导出文件系统时所使用的默认选项。 /etc/amd.conf 文件, 则定义了更多关于 amd 的高级功能选项。

请参考 amd(8)amd.conf(5) 联机手册, 以了解进一步的情况。

30.3.6. 与其他系统集成时的常见问题

Contributed by John Lind.

某些特定的 ISA PC 系统上的以太网适配器上有一些限制, 这些限制可能会导致严重的网络问题, 特别是与 NFS 配合使用时。 这些问题并非 FreeBSD 所特有的, 但 FreeBSD 系统会受到这些问题的影响。

这样的问题, 几乎总是在当 (FreeBSD) PC 系统与高性能的工作站, 例如 Silicon Graphics, Inc., 和 Sun Microsystems, Inc. 的工作站联网时发生。 NFS 挂接能够正常工作, 而且一些操作也可能成功, 但服务器会很快变得对客户机不太理会, 虽然对其他客户机的请求仍然能够正常处理。 这种情况通常发生在客户端, 无论它是一个 FreeBSD 系统或是终端。 在许多系统上, 一旦发生了这样的问题, 通常没办法正常地关闭客户机。 唯一的办法通常是让终端复位, 因为这一 NFS 状况没有办法被解决。

尽管 正确的 解决办法, 是为 FreeBSD 系统配备一块高性能的、 适用的以太网适配器, 然而也有办法绕过问题并得到相对满意的结果。 如果 FreeBSD 系统是 服务器, 则在客户机挂接时, 应该指定 -w=1024。 如果 FreeBSD 系统是 客户机, 则应加入 -r=1024 参数。 这些选项可以通过在对应的 fstab 的第四个字段加入, 以便让客户机能够自动地挂接, 或者通过 mount(8)-o 参数在手工挂接时指定。

还需要注意的是另一个问题, 有时会被误认为是和上面一样的问题。 这个问题多见于 NFS 服务器和客户机在不同的网络上时。 如果是这种情况, 一定要 确定 您的路由器确实把必需的 UDP 信息路由到了目的地, 否则您将什么也做不了。

下面的例子中, fastws 是主机 (接口) 的名字, 它是一台高性能的终端, 而 freebox 是另一台主机 (接口) 的名字, 它是一个使用较低性能的以太网适配器的 FreeBSD 系统。 同时, /sharedfs 将被导出成为 NFS 文件系统 (参见 exports(5)), 而 /project 将是客户机上挂接这一导出文件系统的挂接点。 所有的应用场景中, 请注意附加选项, 例如 hardsoft 以及 bg 可能是您的应用所需要的。

关于 FreeBSD 系统 (freebox) 作为客户机的示范 /etc/fstab 文件, 见于 freebox 之上:

fastws:/sharedfs /project nfs rw,-r=1024 0 0

freebox 上手工挂接:

# mount -t nfs -o -r=1024 fastws:/sharedfs /project

以 FreeBSD 系统作为服务器的例子, 是 fastws 上的 /etc/fstab

freebox:/sharedfs /project nfs rw,-w=1024 0 0

fastws 上手工挂接的命令是:

# mount -t nfs -o -w=1024 freebox:/sharedfs /project

几乎所有的 16-位 以太网控制器, 都能够在没有上述读写尺寸限制的情况下正常工作。

对于那些关心到底是什么问题的人, 下面是失败如何发生的解释, 同时这也说明了为什么这是一个无法恢复的问题。 典型情况下, NFS 会使用一个 为单位进行操作, 其尺寸是 8 K (虽然它可能会将操作分成更小尺寸的分片)。 由于最大的以太网包尺寸大约是 1500 字节, 因此 NFS 会分成多个以太网包, 虽然在更高层的代码看来它仍然是一个完整的单元, 并在接收方重新组装, 作为一个整体来 确认。 高性能的工作站, 可以将构成 NFS 单元的包迅速发出, 其节奏会快到标准允许的最大限度。 在容量较小的卡上, 后来的包会冲掉同一单元内的较早的包, 因而整个单元无法被重建或确认。 其结果是, 工作站将超时并重试, 但仍然是完整的 8 K 单元, 这一过程将无休止地重复下去。

如果将单元尺寸限制在以太网包尺寸之下, 我们就能够确保每一个以太网包都能够被独立地接收和确认, 从而避免了上面的死锁情形。

溢出在高性能工作站将数据库投向 PC 系统时仍会发生, 但在更好的网卡上, 能够保证这类溢出不会在每一个 NFS 单元 上都发生。 当出现溢出时, 被影响的单元被重传, 因而此时有很大的机会它将被正确接收、 重组, 并确认。

本文档和其它文档可从这里下载: ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

如果对于FreeBSD有问题,请先阅读 文档,如不能解决再联系 <questions@FreeBSD.org>.

关于本文档的问题请发信联系 <doc@FreeBSD.org>.