如何更改 Debian 10 的启动根分区?
我想从远程减小位于 LVM 逻辑卷上的根文件系统的大小,这仅通过 SSH 进行,而无需启动到 Live CD。
因为我们无法在安装时缩小 rootfs,所以我认为我只需克隆现有的 rootfs,启动到该 rootfs 并从那里进行调整大小,然后启动到原始 rootfs 并删除临时 rootfs。
我尝试在虚拟机中使用 Ubuntu Server 18.04,因为据我所知,它使用与 Debain 10 相同的“启动链”。但是,我无法可靠地将克隆的分区设置为 root。重新启动后,我检查了一下mount
,发现原始 root 仍在使用,尽管
/etc/fstab
已经升级/boot/grub/grub.cfg
已经升级initramfs
已经升级
当前配置
- 1TB RAID1
md0
- 4TB RAID1
md1
- 光伏开启
md0
- 光伏开启
md1p1
vg0
具有两个 PV 的VG- LV
root
作为原始根文件系统 (UUIDxxx
) - LV
newroot
作为临时根文件系统 (UUIDyyy
) - ext4 开启
vg0-root
(UUIDaaa
) - ext4 开启
vg0-newroot
(UUIDbbb
)
/etc/fstab
已相应更改(替换设备映射器路径)。
到目前为止,我已经将整个旧根 rsyncaaa
到新根,我用和替换bbb
了每个出现的 UUIDaaa
和(注意:我没有使用或 UEFI 启动)。xxx
bbb
yyy
/boot/grub/grub.cfg
grub2
initramfs
已使用 进行更新update-initramfs -u
(修复后/etc/initramfs-tools/conf.d/resume
)。
按照这个顺序。但我在虚拟机中的测试要么直接启动到旧根目录,要么让我进入 GRUB 救援 shell。
update-grub
识别newroot
卷并在中添加匹配的条目grub.cfg
,在我的测试虚拟机启动时手动选择它们(无法通过 SSH 实现......)也启动了旧的根。
我还看到了ROOT
对/etc/initramfs-tools/initramfs.conf
根分区进行硬编码的选项:
当无法传递任何 root bootarg 时,允许可选的 root bootarg 硬编码。root bootarg 会覆盖该特殊设置。
但是由于我的系统中有一个 root 的 bootarg,因此grub.cfg
此设置不会生效。
为了在下次启动时使用另一个 UUID 作为 root,还需要配置什么?
答案1
原来我忘了替换 root= bootarg /boot/grub/grub.cfg
...
为了完整起见:
如何在没有 Live 系统的情况下通过 SSH 将根分区移动到 LVM 中的另一个 PV
注意:务必备份重要数据!此方法是一种破解方法,不应在生产系统上使用。无论如何,在 LV 克隆和从新根分区启动之间写入的数据将始终丢失。
在其他磁盘上创建新的 LVM
fdisk /dev/sdb #Create new partition for PV (sdb1)
pvcreate /dev/sdb1
vgcreate vg1 /dev/sdb1
lvcreate -n newroot -L10G vg1 #Size has to be larger than effective usage on current root
mkfs.ext4 -L newroot /dev/mapper/vg1-newroot
收集有关新 LVM 的信息
lvdisplay
vgdisplay
pvdisplay
blkid
以下命令将引用此处提供的信息:
- $pv0uuid = 旧 PV 的 UUID
- $pv1uuid = 新 PV 的 UUID
- $vg{0,1}uuid = {旧,新} VG 的 UUID
- $lv{0,1}UUID = {旧,新} LV 的 UUID
- $root{0,1}UUID = {old,new} 根文件系统的 UUID
- $vg{0,1} = {旧,新} VG 的名称
- $lv{0,1} = {旧,新} LV 的名称
并将/etc/grub/grub.cfg
呈现为$grubcfg
。对于 UEFI 系统,这很可能是/boot/grub2/grub.cfg
。
bash
我建议在使用时将这些设置为变量pv0uuid=xxxxxx-xxxx...
,以便可以复制粘贴下面的命令。
在 GRUB 配置中设置新根
这些命令将替换 GRUB 配置中的文本:
sed -i "s/$pv0uuid/$pv1uuid/g" $grubcfg
sed -i "s/$vg0uuid/$vg1uuid/g" $grubcfg
sed -i "s/$lv0uuid/$lv1uuid/g" $grubcfg
sed -i "s/$root0uuid/$root1uuid/g" $grubcfg
sed -i "s/$vg0/$vg1/g" $grubcfg #BEWARE COMMON NAMES
sed -i "s/$lv0/$lv1/g" $grubcfg #BEWARE COMMON NAMES
sed -i "s/\/dev\/mapper\/$vg0-$lv0/\/dev\/mapper\/$vg1-$lv1/g" /etc/fstab #BEWARE COMMON NAMES
小心常见名称:
sed
将取代每一个匹配文本的出现,因此建议手动进行这些更改,因为替换root
在 GRUB 或 fstab 配置的其他地方使用的单词将使其无效!
我建议使用nano
并搜索(CTRL+W
)VG 和 LV 名称并手动替换它们。还建议搜索 PV 设备名称,以防万一……
克隆根卷
mount /dev/mapper/$vg1-$lv1 /mnt
rsync -rAa --one-file-system / /mnt/
umount /mnt
重启
重启(并祈祷)。验证新的 LV 是否已安装到/
。
删除旧的 LVM
lvremove /dev/$vg0/*
vgremove $vg0
pvremove /dev/sda2 #Path to $pv0uuid
清理
可选,但建议
- 最后删除旧的 VG
/etc/lvm/archive
,否则每次启动时都会搜索它并导致延迟 update-grub
update-initramfs -u
笔记
在 Ubuntu 18.04 上测试,其他发行版可能会以不同的方式处理 GRUB 配置(关于 UUID 与设备路径和更新命令)。
显然,请事先停止所有不必要的服务以尽量减少数据丢失。
可能有一种方法可以避免(大多数)数据丢失,即使用 systemd 目标、自定义脚本和 LVM 快照。在重启之前的最后一刻,必须再次同步数据$lv0
。超出了本文的范围...$lv1
如果/boot
不是单独的分区,请$grubcfg
在重新启动之前仔细检查新的根目录。
答案2
不确定这是否会对您有帮助,但以下是我成功尝试缩小 LV 上的根分区的方法:
- 创建根分区快照。确保它已分配一些空间,因为您将对其进行更改。
- fsck 快照。
- 调整快照大小(缩小它)并确保在文件系统顶部和 LV 目标大小边界之间有一些缓冲区 - 只是为了安全起见。
- 将快照合并回你的 rootfs LV。
- 重启。此时合并实际上已经完成(可能是在启动期间)。
- 重新启动后 - 缩小 rootfs 卷并可能再次调整 rootfs 大小 - 这样它会填充 LV 顶部的任何空间。
有一个缺点:您将在步骤 1 和步骤 5 之间丢失一些数据,并且您可能会在步骤 1 中遇到一些不一致的情况(取决于正在使用的 FS)-因为您在实时文件系统上创建了快照。
对于我来说它的效果出奇的好。
在理想情况下,步骤 1 将在启动期间完成,在重新/安装 rootfs rw 之前完成,因此快照是干净的。我还没有弄清楚如何从 dracut 执行此操作 - 我尝试使用的工具在那里不起作用。