Linux硬盘迁移日记
Zane

前言

原有的是一块 1TB 的机械硬盘,不论是开机还是日常的读取/写入文件都非常的慢,并且在使用一些组件的过程中也发现了性能的瓶颈,就想通过更新硬盘看看能否解决一些问题,但是由于工作上有很多产品的 license 激活非常的麻烦,安装 Qt 、编译 opencv 的流程也十分的繁琐,就诞生了这次的硬盘迁移工作。

并且迁移整个硬盘数据是我头一次遇到,更何况是 Ubuntu Linux 系统。所有也是踩了很多的坑。

正文

dd

起初,通过一系列搜索引擎查到的资料是直接使用 dd 命令,直接对两个分区中的数据进行复制或转换,因为是直接复制块设备内容,是块级别的,不需要知道文件系统结构。

机械硬盘的分区有四个,由 x86 的 UEFI 分区、Linux Boot 分区、Linux Swap 分区、Linux 根文件系统分区,大小如下:

1
2
3
4
5
Filesystem      Size  Used 
/dev/sda1 1G 0.3G
/dev/sda2 3.9G 0.8G
/dev/sda3 16G
/dev/sda4 900G 39.1G

但是当我将新的硬盘接入,并使用 cfdisk 进行同样大小分区的时候,发现固态的大小远远不足机械硬盘的大小,导致最终的根文件系统分区(/dev/sda4)只有 90 个G,此时就产生了 dd 的底层逻辑是将数据文件传入相应分区还是将整个分区中的数据内容平移到指定分区。

不出所料,在前三个分区都 dd 成功后,最后一个分区因磁盘空间不足而中断。

scp

还通过博客看到在 Linux 启动盘中将相应的两个分区进行挂载,并使用 scp 命令直接将挂载根目录的文件拷贝到目标挂载目录,但是在等了很久的传输过程后,依旧以磁盘写满告终。

压缩空闲分区

在前面两个小坑之后,验证由于分区过大导致的拷贝目标分区写满的问题,于是想到将源分区进行 resize 至 40G 以下,这样可使用 dd 命令。

但是在卸载后进行压缩发现原有的根文件系统已经无法正常挂载,于是只能恢复,回到起点。

rsync

该工具主要用于文件和目录的同步,可以在本地系统之间或通过网络在远程系统之间同步文件和目录,同时还会比较源和目标文件,仅仅传输发生变化的部分。

  1. 使用 Live 系统: 首先,确保你使用 Live Linux 系统(比如 Live CD 或 USB)引导计算机,以便在系统运行时对根文件系统分区进行操作。

  2. 在 Live 环境中调整目标分区大小: 使用分区工具(如 gparted)在目标硬盘上调整目标分区的大小,确保它足够大以容纳源分区的数据。

  3. 挂载目标和源分区: 在 Live 环境中挂载目标和源分区:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 创建目录用于挂载目标分区
    sudo mkdir /mnt/target

    # 挂载目标分区
    sudo mount /dev/sdb4 /mnt/target

    # 创建目录用于挂载源分区
    sudo mkdir /mnt/source

    # 挂载源分区
    sudo mount /dev/sda4 /mnt/source
  4. 复制文件系统数据: 使用 rsync 命令复制源分区的文件系统数据到目标分区:

    1
    sudo rsync -aAXv /mnt/source/ /mnt/target/

    这个命令将递归地复制文件,保留权限、所有者和时间戳等信息。

  5. 更新目标分区的 /etc/fstab 使用编辑器(如 nanovim)编辑目标分区的 /mnt/target/etc/fstab 文件,确保其中的根分区条目(通常是 /)指向正确的分区。

  6. 更新目标分区的 GRUB 配置(如果需要,也可以先手动在 grub 进入系统验证): 如果使用 GRUB 引导,请确保更新目标分区上的 GRUB 配置以反映新的根分区。可以使用以下命令重新安装 GRUB:

    1
    sudo grub-install --root-directory=/mnt/target /dev/sdb

    请将 /dev/sdb 替换为目标磁盘。

  7. 更新目标分区的 UUID: 使用 blkid 命令获取新目标分区的 UUID,并更新 /mnt/target/etc/fstab/mnt/target/boot/grub/grub.cfg 文件中的 UUID。

  8. 卸载分区并重启: 在完成以上步骤后,卸载分区并重启计算机:

    1
    2
    sudo umount /mnt/target
    sudo umount /mnt/source

检查文件系统

在我这次流程中,对前三分区进行数据传入操作后,通过 gparted 工具查看发现分区标识上有红色感叹号,但是没深究其原因以及其造成的影响,似乎是指分区表有问题,但是在该工具有一个检查功能,在对分区逐个检查后感叹号就消失了。

然后重新启动计算机。

恢复 grub

理论上如果没执行上述的第 6 步,再次重启计算机,就会进入 grub 中,可以通过手动启动的方式进入系统。

  1. 使用 ls 命令,找到 Ubuntu 的安装分区是哪一个。

  2. 找到 Linux 的 /boot分区,并设置 Linux 内核镜像及 / 所在分区

    1
    grub> linux /boot/vmlinuz-4.8.0-36-generic ro text root=/dev/sda4
  3. initrd 命令指定 initrd 文件

    1
    2
    grub> initrd /boot/initrd.img-4.8.0-36-generic
    grub> boot // 启动系统
  4. 进入系统后在终端执行两条命令,即可修复 grub

    1
    2
    sudo update-grub
    sudo grub-install /dev/sda

参考

dd 的基本语法如下:

1
2
bashCopy code
dd if=input_file of=output_file bs=block_size count=number_of_blocks
  • if(input file):指定输入文件的路径。
  • of(output file):指定输出文件的路径。
  • bs(block size):指定每个块的大小。
  • count:指定要复制的块数。

dd 的主要用途包括:

  1. 复制块设备或文件:

    1
    2
    bashCopy code
    dd if=/dev/sda of=/dev/sdb bs=4M

    这个例子将硬盘 /dev/sda 的内容复制到硬盘 /dev/sdb

  2. 创建空白文件或空白块:

    1
    2
    bashCopy code
    dd if=/dev/zero of=output_file bs=1M count=100

    这个例子创建了一个大小为 100MB 的空白文件。

  3. 备份和还原 MBR(主引导记录):

    1
    2
    bashCopy code
    dd if=/dev/sda of=mbr_backup bs=512 count=1

    这个例子备份了硬盘 /dev/sda 上的 MBR。

  4. 磁盘镜像的创建和还原:

    1
    2
    bashCopy code
    dd if=/dev/sda of=disk_image.img bs=4M

    这个例子创建了整个硬盘 /dev/sda 的镜像文件。

  5. 随机数生成:

    1
    2
    bashCopy code
    dd if=/dev/random of=random_data bs=1M count=1

    这个例子生成了一个包含 1MB 随机数据的文件。