如何迁移和移动 UNIX 文件系统

    了解如何在活动的系统中传输整个文件系统,包括如何创建、复制和重新实现新的文件系统。如果出现了 UNIX® 磁盘、系统故障或只是填满了文件系统,那么您需要创建新的分区和文件系统,并对相关内容进行复制。甚至可能需要将新的分区装入到适当的地方,以保持重要的文件和组件的位置。更复杂的情况是,您需要在活动的系统中完成这项工作,需要保持文件权限、所有权和可能存在的命名管道以及其他组件。高效地传输这些组件并保持所有这些信息,是迁移过程中的重要部分。
  


关于本系列
  
    通常,UNIX® 管理员都拥有一套常用的辅助进程管理的实用工具、诀窍和系统。本文提供了各种用于简化各个过程的关键实用工具、命令行链和脚本。这些工具中的一部分来自于操作系统,而大部分的诀窍则来源于长期的经验积累和减轻系统管理员的工作压力的要求。本系列文章主要专注于最大限度地利用各种 UNIX 环境中可用的工具,包括简化异类环境中的管理任务的方法。
  
  移动 UNIX 目录或文件系统
  
    在许多情况下,您可能需要将 UNIX 文件系统从一个设备或硬盘分区移动到另一个设备或硬盘分区,或者需要移动文件系统中的内容以释放所占用的空间,在处理这些情况的过程中,都需要创建新的文件系统。可能是因为设备将会出现故障,或者仅仅只是耗尽了空间。您可以在运行于单用户模式的系统或者活动的 和运行的系统(需要确保文件在移动的过程中仍然可用)中完成这项任务。
  
    在后面的这种情况下,即对活动的文件系统进行迁移时,您可能需要在某个应用程序运行的过程中对其进行移动。对于上面的这两种情况,您可能需要移动与系统相关的文件系统(如 /usr 或 /var),无论是否运行于单用户模式,该文件系统都有可能正在被使用。
  
    在任何文件系统的移动操作中,您必须确保正确地将数据复制到新的目标。作为一个典型的示例,假定您的系统的文件/磁盘布局和使用情况如清单 1 所示。
  
清单 1. 示例文件/磁盘布局和使用情况




Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda3 7692908 6467756 1225152 84% /
udev 517560 184 517376 1% /dev
/dev/hda1 115377640 1743668 107773060 2% /var/lib/mysql
/dev/hdb1 115380192 14604460 94914696 14% /export/data
/dev/hde1 96132940 3962940 87286644 5% /export/home
/dev/hde4 22960280 133484 21660480 1% /tmp
none 517560 0 517560 0% /dev/shm



  
    正如您在清单 1 中所看到的,根文件系统已使用了百分之八十四,您可能应该将处于单个分区的根文件系统中的目录移动到新的分区或设备,以确保根文件系统不会被占满。
  
    最好是移动显著影响希望释放空间的文件系统中的具有特定用途的单个目录。例如,在这个示例中,您可能希望将 /var 或 /usr 目录移动到它自己的文件系统。移动多个更小的目录,效率会比较低。您所需要做的只是轻松地移动单个目录以释放所占用的空间。
  
    在有些情况下,您可能需要将现有的分区移动或复制到一个新的位置(例如,在设备可能出现故障的情况下)。这里,已经解释了究竟是应该选择目录还是现有的文件系统。
  
    在本文中,假设您已经添加了一个新的硬盘设备或具有备用的硬盘设备或分区,以用作目录或文件系统的移动目标。
  
  移动数据的快速指导
  
    移动文件系统或将现有的目录移动到新的文件系统,基本操作序列如下:
  
  选择要进行复制的数据。
  创建一个新的分区。
  在该分区上创建一个新的文件系统。
  将该分区装入到一个临时目录。
  将数据复制到这个临时目录。
  对原始目录进行重命名。
  创建新的装入点。
  装入这个文件系统。



    理想情况下,在完成这些操作之后,您应该重新启动计算机,尽管这并不总是必需的或可能的,但是应该在允许的情况下尽早重新启动计算机。


    让我们对序列中的每个步骤进行更仔细的研究。
  
  创建新的分区和文件系统
  
    在创建新的分区和文件系统之前,首先确保可用大小和空间与要移动到新的文件系统中的文件/目录的大小相匹配。要完成这项工作,最简单的方法是使用 du 工具来确定当前文件/目录的大小。例如,如果您打算对示例系统中的 /usr 目录进行移动,可以使用如清单 2 所示的命令。
    
清单 2. 移动示例系统中的 /usr 目录




$ du -sk /usr
3923068 /usr



    -s 选项确保生成整个目录的摘要信息,而不是所有内容的信息,并且 -k 选项确保以 KB 为单位显示目录大小。从上面的输出结果中您可以确定,需要至少 4GB 大小的新的分区。
  
    如果您将现有的文件系统(而不是现有的文件系统中的单个目录)移动到一个更大的分区,那么可以使用 df 的输出来确定当前文件系统的大小。
  
    在知道了其大小之后,理想情况下,您应该创建一个比所需大小大百分之二十五的新的分区,并且至少要大百分之十。对于上面的示例文件系统,您至少需要创建一个 5GB 大小的新的分区。
  
    要创建新的分区和文件系统,需要使用适合于您的操作系统的工具。例如:
  
    在 Linux® 中,您需要使用 fdisk 对物理硬盘上的各个分区进行配置,并使用 mke2fs 或 mkfs.* 创建命令中的一个,以便在新的分区上创建合适的文件系统。



  在 Solaris SPARC 系统中,可以使用 format 来创建并配置分区。在 Solaris x86 系统中,在使用 format 对 Sun 分区表进行配置之前,您可能还需要使用 fdisk 来配置磁盘分区。然后,您可以使用 newfs(或某个文件系统特定的命令)来创建文件系统。



    在 AIX® 中,可以使用 mkvg、chpv 或某个其他的卷管理工具为新的分区创建合适的分区或卷组。然后,可以使用 crfs 创建文件系统。



  创建了文件系统之后,在对数据进行复制时,需要在进行载入的新文件系统中创建一个新的目录。例如,我个人喜欢在相似的位置创建新的文件系统,并且通过名称将其标识为临时文件系统。
  
  对于上面的 /usr 示例,我将创建一个新的目录 /mnt/usr.tmp,并将新的文件系统载入到该目录。
  
  复制信息
  
    事实上,复制信息可能是整个过程中最简单的部分,但是选择合适的工具将直接影响到信息传输的有效性和效率。然而,您应该确保将文件复制到正确的位置,要避免覆盖现有的数据。
  
    有许多种不同的方法可以完成这个任务,但是主要的两种解决方案是使用基本的 cp 工具或 tar 工具。前者是一种非常快速的方法,但是在某些操作系统中,对于一些非标准的文件,如管道和设备,可能会出现问题。tar 工具可能是一种速度较慢的替代方法,但是在传输其他类型的文件时,它更加可靠并且提供了关于复制过程的更加可视化的反馈信息。
  
    无论您使用哪一种方法,都应该确保不要对源文件系统中的任何文件进行更新。请记住,您所建立的任何副本仅包含在进行复制操作时对应的文件中所包含的数据。如果在进行复制的过程中对该文件系统中的文件进行了更新,那么新的文件系统中的文件可能是不完整的并且受到了损坏。
  
  使用 cp
  
    cp 工具提供了一个递归复制选项 (-r),使用该选项可以将所有的文件、目录以及这些目录中的文件全部复制到目标。您还可以使用 -p 选项来保持所有权和复制的文件的权限。如果您希望确保新的文件系统保留源文件系统的安全细节,那么这是至关重要的。在大多数情况下,这样做是必须的。
  
    要将文件从现有的目录复制到新的位置,请执行以下步骤:
  
    改变到新的目标目录并确认位于正确的位置(请参见清单 3)。
    
  清单 3. 改变目标目录




$ cd /mnt/usr.tmp
$ pwd
/mnt/usr.tmp



  
    将文件从旧的目录复制到当前(新的)目录,如清单 4 所示。
  
    清单 4. 将文件复制到新的目录




$ cp -pr /usr/* .



    您应该进行快速的验证以确保成功地复制了这些文件。简单的 ls 即可以得到清楚的指示(请参见清单 5)。稍后您将了解到更详细的检查方法。
    
  清单 5. 验证成功地复制了这些文件




$ ls -l /usr
total 238
drwxr-xr-x 2 root bin 1024 Apr 20 13:11 4lib/
lrwxrwxrwx 1 root root 5 Apr 20 12:40 5bin -> ./bin/
lrwxrwxrwx 1 root root 9 Apr 20 12:34 X -> ./openwin/
drwxr-xr-x 6 root bin 512 Apr 20 12:42 X11/
lrwxrwxrwx 1 root root 3 Apr 20 12:41 X11R6 -> X11/
lrwxrwxrwx 1 root root 10 Apr 20 13:03 adm -> /var/adm/
drwxr-xr-x 10 root bin 512 Apr 20 12:59 apache/
drwxr-xr-x 8 root bin 512 Apr 20 12:47 apache2/
drwxr-xr-x 8 root bin 512 Apr 20 12:53 appserver/
drwx—— 8 root bin 512 Apr 20 12:53 aset/
drwxr-xr-x 4 root bin 16384 Apr 20 13:17 bin/
drwxr-xr-x 4 root bin 512 Apr 20 12:33 ccs/

lrwxrwxrwx 1 root root 10 Apr 20 12:32 tmp -> /var/tmp/
drwxr-xr-x 4 root bin 2048 Apr 20 13:00 ucb/
drwxr-xr-x 4 root bin 512 Apr 20 13:17 ucbinclude/
drwxr-xr-x 3 root bin 1024 Apr 20 13:17 ucblib/
drwxr-xr-x 7 root bin 512 Apr 20 13:03 vmsys/
drwxr-xr-x 5 root bin 512 Apr 20 12:44 xpg4/
drwxr-xr-x 3 root bin 512 Apr 20 12:40 xpg6



  如果您发现没有正确地复制某些文件或者符号链接和其他特殊类型的文件,那么您可能需要尝试使用 tar。
  
  使用 tar
  
   与 cp 相比,tar 工具提供了许多的好处。首先,也是最重要的,对于非标准的文件类型,它通常更加可靠。其次,因为它能够提供关于复制的文件的可视化反馈信息,所以使用它将文件复制到新的系统会更加方便。最后一点也非常重要,您可以使用 tar 创建文件系统的存档文件,万一在出现问题时,该文件可以作为源目录/文件系统的备份。在处于单用户模式的计算机的用户文件系统中,这种 tar 文件方法可以用来创建新的文件系统内容,而无需将新的目标装入到临时目录装入点。
  
    使用 tar 进行文件复制的最好的方法是,通过管道将 tar 创建的文件传递到位于新的位置进行文件提取的另一个 tar。清单 6 中给出了一个这样的示例。
  
  
  清单 6. 使用 tar 进行文件复制




$ cd /usr
$ tar cfp – ./* |(cd /mnt/usr.tmp; tar xvfp -)



   第一个 tar 中的 c 参数告诉 tar 创建一个存档。v、f 和 p 选项分别指定输出详细信息(显示正在添加或提取的文件)、对文件(而不是磁带设备)进行写入/读取、保持权限和所有权。
  
   清单 6 中的命令行能够正常工作,这是因为在管道的后半部分中,在从标准输入读取管道的前半部分中创建的 .tar 文件之前,首先改变到了目标目录。
  
    如果您需要创建一个 .tar 文件并使用这种方法,而不是执行直接的复制,那么您必须拥有一个能够容纳源目录中所有文件的文件系统。清单 7 介绍了进行复制的过程。
    
清单 7. 进行复制的过程




$ cd /usr
$ tar cfp /tmp/usr.tar ./*
$ cd /mnt/usr.tmp
$ tar xvfp /tmp/usr.tar



  无论使用哪一种解决方案,您将在每个文件复制到/复制出存档文件时获得相应的报告,假设您使用了 v 命令行选项(请参见清单 8)。
    
清单 8. 打印出复制过程




a ./4lib/ 0K
a ./4lib/libX.so.1.0 symbolic link to ./libX11.so.4.3
a ./4lib/libX11.so.4.3 216K
a ./4lib/libXaw.so.4.0 208K
a ./4lib/libXmu.so.4.0 72K
a ./4lib/libXol.so.3.1 1056K
a ./4lib/libXt.so.4.1 264K
a ./4lib/libce.so.0.0 48K
a ./4lib/libdeskset.so.0.1 64K
a ./4lib/libdga.so.1.0 40K
a ./4lib/libhelp.so.1.0 24K
a ./4lib/libolgx.so.3.1 56K
a ./4lib/libtt.so.1.1 848K
a ./4lib/libttstub.so.1.1 32K
a ./4lib/libxview.so.3.73 1328K
a ./4lib/libdl.so.1.0 symbolic link to //lib/libdl.so.1
a ./4lib/libc.so.1.9 403K
a ./4lib/libc.so.2.9 402K



  使用 tar 和直接文件系统交换
  
    要将文件系统的内容复制到新的位置,而无需创建临时装入点,您必须首先拥有足够容纳源目录中所有文件的空间。
  
    如果使用新的文件系统来替代一个目录,可以执行以下操作:
  
    和前面一样,创建新的分区和文件系统。



    创建源目录的 .tar 文件(请参见清单 9)。
  
  
  清单 9. 创建 .tar 文件


$ cd /home
$ tar cfvp /tmp/home.tar

  对源目录进行重命名(请参见清单 10)。
    
  清单 10. 对源目录进行重命名


$ cd ..
$ mv home home.old

  
    创建目录,并将其权限和所有权设置为与原始目录相同。
    将新的文件系统装入到这个新的目录。
    提取 .tar 文件(请参见清单 11)。
  
  
  清单 11. 提取 .tar 文件


$ cd home
$ tar xvfp /tmp/home.tar

    如果您需要为现有的文件系统改变分区(如清单 10 中所示),那么命令序列是类似的,但是您需要卸载现有的文件系统,而不是对目录进行重命名(请参见清单 12)。
  
  
清单 12. 为现有的文件系统改变分区


$ cd ..
$ umount /home

  
    这种方法仍然是安全的,这是因为您拥有旧分区上源文件系统的完整副本。无论在哪一种解决方案中,您都没有删除内容或源数据。
  
  对复制进行验证
  
    无论使用 cp 还是 tar,您始终都应该验证复制过程是否成功完成。尽管 tar 对所复制的文件进行了证实(使用 v 选项),但是您应该确保在新的文件系统中正确地创建了这些文件。
  
    首先,检查 du 对旧的和新的系统的输出(请参见清单 13)。
  
  
  清单 13. 检查 du 的输出


$ du -sk /usr
3923068 /usr
$ du -sk /mnt/usr.tmp
3923068 /mnt/usr.tmp

  
    这两个数字应该是相等的,然而,根据新文件系统的类型以及旧文件系统/目录和新文件系统/目录中对应的文件和目录的分配大小的不同,您可能会发现它们在大小上有些细微的差异。
  
    另一种好的测试方法是,比较源和目标文件/目录的数目。您可以使用简单的 find command 来完成这项工作,如清单 14 所示。
  
  
  清单 14. 比较源和目标文件/目录的数目


$ find /usr |wc -l
347001
$ find /mnt/usr.tmp |wc -l
347001

  
    如果您将文件从一个文件系统复制到另一个文件系统,那么还有一种好的测试方法,即比较索引节点数目,这将显示分配了多少个索引节点。如果您将文件从一个文件系统复制到另一个与其类型完全相同的文件系统,那么所使用的索引节点的数目应该是相等的。可以使用带 -i 命令行选项的 df 命令获取索引节点的统计信息,或者在传统的 UNIX 系统中,不带参数的 df 可以输出创建“文件”的数目。
  
    清单 15 中的示例来自于 Linux 系统。
  
  
  清单 15. 比较索引节点数目


$ df -i /usr
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda3 977280 411959 565321 43% /

  清单 16 中的示例来自 Solaris。
  
  
  清单 16. 在 Solaris 中比较索引节点数目


$  /bin/df /usr
/usr (/dev/dsk/c0t0d0s3 ): 9076010 blocks 863695 files

  
  更新系统以反映新的组织结构
  
    此时,您应该已经拥有了一个新的文件系统,其中包含了要移动到这个新文件系统的文件系统或目录的副本。现在,您应该对系统文件(特别是文件系统装入信息)进行更新,以反映新的结构。该信息存储在 /etc/fstab、/etc/vfstab 中,或通过特定的管理工具来访问,如 HP-UX 上的 SAM。
  
    如果您需要对现有文件系统中的目录进行迁移,可以执行下面的操作:
  
     对原始目录进行重命名。
     创建新的目录。
     使用 chown 和 chmod 设置新目录的所有权和权限。
     理想情况下,您应该重新启动系统以确保使用新的布局。如果您将文件系统从一个设备迁移到另一个设备,那么必须重新启动。通常,您可以卸载现有的文件系统,特别是当它为系统目录(换句话说,/var 或 /usr 下的系统目录)时。
  
    如果无法进行重新启动,可以手动地将新的系统装入到新的装入点,然后尽可能早地进行重新启动。
  
    在重新启动并证实一切正常工作之后,可以删除旧的目录或重用旧的分区。
  
  结束语
  
    在许多情况下,需要对活动或非活动的 UNIX 文件系统进行复制。可能是因为耗尽了磁盘空间,所以文件系统需要更大的分区来安装软件,甚至是因为硬件将会出现故障。在这些情况下,您需要使用本文中介绍的技巧,将现有的文件复制到新的文件系统。
  
    这种复制操作本身存在一定的陷井,即对活动的文件系统进行复制可能是有风险的,特别是在打开了多个文件的情况下。您还应该注意,务必避免用要复制的文件意外地覆盖分区或现有的文件。然而正如您所看到的,经过周密的考虑,可以高效地、可靠地对文件进行迁移,以充分利用更大的空间,即使是在活动的系统中也可以实现。