5. 客户端设置,创建根文件系统

累了吗?不,你没有。记住你是个英雄。棘手的部分来了。我们将(呃...将)构建客户端的根文件系统。这应该不会很难,但你可能需要使用试错法。

创建根文件系统最简单的方法是使用一个已经可以正常工作的文件系统,并根据无盘操作的需求对其进行定制。当然,如果你喜欢 :=),你也可以手动构建一个(就像在过去的好时光一样),但我不会在这里解释这个。

5.1. 创建初始文件和目录

首先,cd 到你未来的工作站的根目录。你可以安全地创建未来的/home目录,使用 mkdir 命令,或者从你想要的任何地方复制它(你可以使用 cp -a 进行递归复制,保留所有者、组、符号链接和权限)。对于未来的/mnt, /root, /tmp也一样(别忘了 chmod 0 它,这只是实际/tmp我们将要使用的挂载点,因为每个工作站都需要有自己的/tmp)。然后,将一些现有的/bin, /sbin, /boot/usr复制到这个未来的根目录中(使用 cp -a)。你可以使用 mkdir 创建/proc目录,并 chmod 0 它。注意,一些应用程序需要对其用户主目录的写入权限。

目录/lib可以安全地从其他地方复制,但你必须在其中放入正确的模块。为此,请使用以下命令(假设你已经在服务器上的/usr/src/linux中为你的客户端编译了内核,并且根文件系统将位于/nfsroot):
        # cd /usr/src/linux
        # make modules_install INSTALL_MOD_PATH=/nfsroot
      

别忘了把System.map文件放在/nfsroot/boot中。我们必须解决的第一个问题是,根据你的配置,你的系统可能会尝试在启动时对根文件系统运行 fsck。如果机箱中没有硬盘,则不应该这样做。大多数发行版也会在根目录中找到fastboot文件时跳过此 fsck。因此,如果你不打算挂载任何硬盘,请发出以下命令
        # cd /nfsroot
        # touch fastboot
        # chmod 0 fastboot
      
另一种方法是告诉 fsck 检查 NFS 文件系统总是成功
      # cd /nfsroot/sbin
      # ln -s ../bin/true fsck.nfs
    

目录/dev目录也可以安全地从另一个地方复制到/nfsroot。但是必须保留权限和符号链接,所以使用 cp -a。另一种解决方案是使用内核 2.2.x devfs 功能,这将减少内存消耗并提高性能,但此方法的缺点是所有在/dev中创建的符号链接都将丢失。要记住的重点是,每个工作站都需要有自己的/dev,因此如果你计划使用多个客户端并且不使用 devfs,则必须将其复制到 ramdisk 上。

5.2./var/etc目录

我们将为这些目录使用 ramdisk,因为每个客户端都需要有自己的目录。但我们仍然需要在开始时创建它们的标准结构。注意,如果你只使用单个客户端,则不需要这样做。因此,从另一个地方复制这些目录 (cp -a) 到/nfsroot。然后你可以在/var中进行一些清理:你可以删除/nfsroot/var/log/nfsroot/var/run中的所有内容。你可能还可以删除/nfsroot/var/spool/mail中的所有内容,如果你计划通过 NFS 导出它。你还需要删除 /nfsroot/etc 中包含主机特定信息的文件,以便在启动过程中动态构建它们。

启动脚本将必须进行定制,以便挂载文件系统的某些部分:/dev目录,如果你不使用 devfs,/tmp/var/etc目录。以下是一些实现此目的的代码
        # this part only if you don't use devfs
        mke2fs -q -i 1024 /dev/ram0 16384
        mount -n -t ext2 -o rw,suid,dev,exec, \
            async,nocheck /dev/ram0 /dev
        # this part for everyone
        mke2fs -q -i 1024 /dev/ram1 16384
        mount -n -t ext2 -o rw,suid,dev,exec, \
            async,nocheck /dev/ram1 /tmp
        chmod 1777 /tmp
        cp -a /etc /tmp
        mke2fs -q -i 1024 /dev/ram2 16384
        mount -n -t ext2 -o rw,suid,dev,exec, \
            async,nocheck /dev/ram2 /etc
        find /tmp/etc -maxdepth 1 -exec cp -a '{}' /etc ';'
        mount -f -t ext2 -o rw,suid,dev,exec, \
            async,nocheck,remount /dev/ram2 /etc
        mount -f -o remount /
        cp -a /var /tmp
        mke2fs -q -i 1024 /dev/ram3 16384
        mount -t ext2 -o rw,suid,dev,exec, \
            async,nocheck /dev/ram3 /var
        find /tmp/var -maxdepth 1 -exec cp -a '{}' /var ';'
      

如果你计划使用多个客户端,你还需要在启动时动态更改/etc中的文件:包含客户端 IP 和主机名的文件。这些文件取决于你的发行版,但你可以通过几个 grep 轻松找到它们。只需从它们中删除客户端特定的信息,并在你的启动文件中添加代码,以便在启动时重新生成此信息,但只有在新的 /etc 挂载到 ramdisk 上之后! 一种在启动时获取 IP 地址和主机名的方法如下(如果你在工作站的文件系统上安装了 bootpc 软件包)
        IPADDR="$(bootpc | awk '/IPADDR/ \
                                {
                                  match($0,"[A-Za-z]+")
                                  s=substr($0,RSTART+RLENGTH)
                                  match(s,"[0-9.]+")
                                  print substr(s,RSTART,RLENGTH)
                                }
                               ')"

        HOST="$(bootpc | awk '/HOSTNAME/ \
                              {
                                match($0,"[A-Za-z]+")
                                s=substr($0,RSTART+RLENGTH)
                                match(s,"[A-Za-z0-9-]+")
                                print substr(s,RSTART,RLENGTH)
                              }')"

        DOMAIN="$(bootpc | awk '/DOMAIN/ \
                                {
                                  match($0,"[A-Za-z]+")
                                  s=substr($0,RSTART+RLENGTH)
                                  match(s,"[A-Za-z0-9-.]+")
                                  print substr(s,RSTART,RLENGTH)
                                }')"
      
这是一个复杂的解决方案,但我猜它应该在大多数站点上工作。IP 地址也可以通过 ifconfig 的输出获得,主机名可以从 host 命令的输出获得,但这不具有可移植性,因为这些输出因系统而异,具体取决于你使用的发行版和区域设置。

然后,应使用 hostname $HOSTNAME 命令设置主机名。完成此操作后,就可以动态生成包含客户端 IP 地址或主机名的配置文件了。

5.3. 最后细节

现在,是时候对客户端进行微调了。由于/var将被挂载在 ramdisk 上(除非你只有一个客户端),如果你想保留日志,则必须将日志发送到日志服务器。一种方法是删除/nfsroot/etc/syslog.conf文件,并将其替换为以下文件(有关详细信息,请参阅 man syslog.conf)
        *.*     /dev/tty12
        *.*     @dns or IP of the logs server
      
如果这样做,日志服务器将必须运行带有 -r 选项的 syslogd(请参阅 syslogd 手册页)。

如果你使用 logrotate 并且已完成上述操作,则应将 logrotate 配置文件(/etc/logrotate.conf在大多数机器上)替换为空文件
        # rm -f /etc/logrotate.conf
        # touch /etc/logrotate.conf
      
如果你不使用它,只需从 crontab 中删除日志轮换脚本,并且由于你不再在/var/log中拥有日志文件,请在你的日志轮换脚本的开头放置一个 exit 0

/nfsroot/etc/fstab文件中,删除任何与硬盘驱动器、软盘驱动器或 CD-ROM 相关的条目(如果你的工作站上没有这些设备)。为/var/spool/mail目录添加一个条目,该目录应通过 NFS 或任何其他网络文件系统由服务器导出。你可能还想在此文件中为/home目录添加一个条目。

你还可以注释掉运行 newaliases、激活交换分区和运行 depmod -a 的行,并删除/nfsroot/etc/mtab文件。注释掉启动脚本中删除/fastboot, /fsckoptions/forcefsck的行。还要删除或注释掉启动脚本中任何尝试写入根文件系统的行,除非是真正必要的写入,如果使用多个客户端,则所有这些写入都应重定向到某个 ramdisk 位置。

5.4. 尝试...

是时候进行一个小小的尝试了。备份你新创建的/nfsroot。 tar -cvvIf 应该可以正常工作。花一分钟检查一下我们是否遗漏了什么。尝试启动一个客户端。

5.5. 和错误!

仔细查看客户端在启动过程中的屏幕。哦,我没告诉你连接屏幕... 跑起来,森林!跑起来去拿一个。你可能会看到一些错误消息。修复问题,并频繁备份你的/nfsroot。总有一天,客户端会正常启动。在那一天,你将不得不修复关机期间发生的错误;=P。