LVM数据迁移至普通硬盘

注意:请务必做好数据备份,本文的前提是对Proxmox中的VM操作, 利用了PVE的备份和还原能力.

  1. 创建一个一样大小的硬盘并挂载到VM.

  2. 选择一个live系统,这里我们选择 Ubuntu Desktop 24.04.1 LTS

  3. 将live盘设置为启动盘,启动系统,选择 Try Ubuntu 进入 live 环境

  4. 由于我原来的LVM系统盘有三个分区 1M, 1G的/boot, 199G的lvm数据分区,所以需要先拷贝系统,再把boot部分的补上, 具体操作如下:

1
2
3
4
5
6
7
8
...
sda 8:0 0 200G 0 disk
|- sda1 8:1 0 1M 0 part
|- sda2 8:2 0 1G 0 part
|- sda3 8:3 0 199G 0 part
|- ubuntu--vg-ubuntu--lv 252:0 0 199G 0 lvm
sdb 8:16 0 200G 0 disk
...

切换至root用户 sudo su 由于是live系统不需要输入密码

创建几个mount点:

1
2
3
mkdir /mnt/src
mkdir /mnt/srcboot
mkdir /mnt/dst

初始化新磁盘(这里 /dev/sda是原来的磁盘, /dev/sdb 是新的磁盘)

1
2
3
4
5
6
7
8
9
gdisk /dev/sdb
输入 p 查看分区, 当前应该没有分区
输入 n 新建分区
分区类型选择 p (primary)
起始位置 2048 终止位置 4095 HexCode设置为 EF02 (BIOS boot partition)
输入 n 新建分区
分区类型选择 p (primary)
起始位置 4096 终止位置, HexCode保持默认 (8300, Linux filesystem)
输入 w 将改动写入到磁盘

如果原来的磁盘不是GPT格式可以尝试如下命令:

1
2
3
4
5
6
7
fdisk /dev/sdb
输入 p 查看分区, 当前应该没有分区
输入 n 新建分区
分区类型选择 p (primary)
起始位置, 大小 等等全部选择默认
新建完成分区后输入 a 将分区标记为引导分区
输入 w 将改动写入到磁盘

在新的磁盘上创建文件系统

1
2
mkfs -t ext4 /dev/sdb2
注意如果没有创建 BIOS boot 分区, 应该使用 /dev/sdb1

挂载磁盘

1
2
3
mount -o ro /dev/sda2 /mnt/srcboot
mount -o ro /dev/mapping/ubuntu--vg-ubuntu--lv /mnt/src
mount /dev/sdb1 /mnt/dst

安装pv工具以便查看复制进度

1
apt update && apt install pv

开始拷贝数据

1
2
tar -C /mnt/src --preserve-permissions --xattrs --xattrs-include=*.* --numeric-owner -c . | pv | tar -xf - -C /mnt/dst --preserve-permissions --xattrs --xattrs-include=*.* --numeric-owner
tar -C /mnt/srcboot --preserve-permissions --xattrs --xattrs-include=*.* --numeric-owner -c . | pv | tar -xf - -C /mnt/dst/boot --preserve-permissions --xattrs --xattrs-include=*.* --numeric-owner

其中 --perserve-permission 是为了保留权限, 对于 root 用户来说是默认的, 但是为了保险起见还是加上

--xattrs, --xattrs-include=*.* 启用额外属性支持, 并拷贝全部属性. 这样类似/usr/bin/ping等文件的 capability 也会被保存下来.

--numeric-owner 要求 tar 使用数字UID/GID 而不是用户名

给新磁盘文件系统下挂载分区

1
2
cd /mnt/dst
for i in /dev /dev/pts /proc /sys /run; do mount --bind $i .$i; done

修改 /etc/fstab,保证里面 /dev/disk/by-uuid/ 对应的磁盘和新磁盘一致. 通过 lsblk -o NAME,uuid 来查看磁盘的uuid

1
nano /mnt/dstetc/fstab

切换rootfs,安装grub. 再运行 update-grub 更新 grub 配置

1
2
3
4
cd /mnt/dst
chroot .
grub-install /dev/sdb
update-grub

退出 chroot, 关闭系统 shutdown now

  1. 弹出 live CD 和原来的磁盘 (在PVE中对应remove和detach)

  2. 重新启动新的系统,可能会遇到几个问题:

grub 菜单展示了 Ubuntu 但是回车进去报错 you need to load kernel first
这种情况应该是因为当前grub标签 (hd0,gpt2) 跟现实不匹配导致的. (也可能是前面忘记执行了update-grub)
在选择页面按下 c 进入 grub shell

1
2
3
4
5
6
7
8
9
ls -l 确认当前磁盘列表和磁盘的UUID
set prefix=(hd0,gpt2)/boot/grub 注意如果不是GPT格式应该用(hd0,msdos1)
set root=(hd0,gpt2)
insmod normal

insmod linux
linux /boot/vmlinuz root=UUID={磁盘的UUID}
initrd /boot/initrd.img
boot

此时应该就会进入系统了

  1. 如果前面忘了改 /etc/fstab 此时进入新系统后会卡在两个任务上:
1
2
Reached target ....
[ ***] Job dev-disk-by\x2duuid-.....device/start running (9s / 1min 30s)

这个没什么好办法,会卡两次,等三分钟就好了。进入系统后记得把 /etc/fstab 改了,运行 sudo grub-install && sudo update-grub 然后再重启应该就没问题了.

参考

Live-cloning a running Linux installation to a new machine

grub error: you need to load kernel first

How do I list my devices in GRUB?

[SOLVED] Creating a BIOS boot partition using gdisk

GPT fdisk - ArchWiki

How to Install Grub Bootloader in Linux