我有一台运行带有 zfs 根文件系统的 Ubuntu 16.04 的物理机,按照https://github.com/zfsonlinux/zfs/wiki/Ubuntu-16.04-Root-on-ZFS上的说明进行安装
我按照说明安装了引导加载程序:
5.5b 对于 UEFI 引导,安装 GRUB:
grub-install --target=x86_64-efi --efi-directory=/boot/efi \
--bootloader-id=ubuntu --recheck --no-floppy
Run Code Online (Sandbox Code Playgroud)
系统已经正常运行了三个月,有多次重启(主要是停电引起的)。
根池是一个三向镜像:
NAME STATE READ WRITE CKSUM
rpool ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
ata-SAMSUNG_HM500JI_S1WFJ90S818624-part1 ONLINE 0 0 0
ata-ST3250820AS_5QE5BVW5-part1 ONLINE 0 0 0
ata-GB0250C8045_9SF0R2RD-part1 ONLINE 0 0 0
Run Code Online (Sandbox Code Playgroud)
最初我的池中还包含一个热备用。今天早上,我需要在另一台有故障设备的服务器上使用热备件,因此我使用 zpool remove 从系统中删除热备件,关闭电源,然后物理删除备件。
现在服务器无法启动。
我尝试选择所有剩余的三个物理磁盘来启动,但没有任何乐趣。
目前,我已使用 Live CD 重新启动。按照上面安装说明中的早期步骤,我可以看到所有 zfs 池,因此数据都在那里。我认为下一步可能是 chroot 到这个 zpool 中,但考虑到不同的 ROOT 文件系统等,我不确定如何执行此操作。
我猜测 GRUB 引导信息由于某种原因仅安装到被指定为“备用”的磁盘上,而我现在已将其删除。有问题的磁盘现在是另一台服务器上 zfs 镜像的一部分,因此无法将其放回原处。
我的问题是:重新初始化 GRUB 以便服务器启动的最简单方法是什么?我是否需要 chroot 到基于磁盘的系统,或者可以从 live-CD 环境中完成此操作吗?如果是前者,如何正确挂载根池?
大部分抄袭自https://github.com/zfsonlinux/zfs/wiki/Ubuntu-16.04-Root-on-ZFS上的 ZFS 安装说明,以下是我用来让系统再次运行的步骤。
\n启动修复不起作用。
\n1.1 启动Ubuntu Live CD,选择尝试Ubuntu而不安装,然后打开终端(按Ctrl-Alt-T)。
\n1.2 可选:在 Live CD 环境中安装 OpenSSH 服务器:\n如果您有第二个系统,使用 SSH 访问目标系统会很方便。
\n$ sudo apt-get --yes install openssh-server\nRun Code Online (Sandbox Code Playgroud)\n在 \xe2\x80\x9cubuntu\xe2\x80\x9d(Live CD 用户)帐户上设置密码:
\n$ passwd\nRun Code Online (Sandbox Code Playgroud)\n提示:您可以使用 ip addr showscope global 找到您的 IP 地址。然后,从您的主机上,使用 ssh ubuntu@IP 连接。
\n1.3 成为root:
\n# sudo -i\nRun Code Online (Sandbox Code Playgroud)\n1.4 在Live CD环境中安装ZFS:
\n# apt-add-repository universe\n# apt update\nRun Code Online (Sandbox Code Playgroud)\n(忽略有关将旧数据库移开的错误)
\n# apt install --yes debootstrap gdisk zfs-initramfs\nRun Code Online (Sandbox Code Playgroud)\n2.1 检查ZFS池是否已经导入
\n# zpool list\n# zfs list \nRun Code Online (Sandbox Code Playgroud)\n2.2 如果显示“没有可用的数据集”,则跳到步骤 3。如果这些命令中的任何一个都显示池列表,则我们需要导出 zfs 池,以便可以将其挂载到不同的目录中,以便可以 chroot 到它
\n# zpool export rpool\nRun Code Online (Sandbox Code Playgroud)\n3.1 将池导入到非默认位置。-N 标志(don\xe2\x80\x99t 自动挂载)是必要的,否则 rpool root 和 rpool/root/UBUNTU 池都将尝试挂载到 /mnt
\n# zpool import -N -R /mnt rpool\nRun Code Online (Sandbox Code Playgroud)\n3.2 挂载根系统
\n# zfs mount rpool/ROOT/ubuntu\nRun Code Online (Sandbox Code Playgroud)\n3.3 挂载剩余文件系统
\n# zfs mount -a\nRun Code Online (Sandbox Code Playgroud)\n3.4 将 LiveCD 环境中的虚拟文件系统绑定到新系统并 chroot 到其中:
\n# mount --rbind /dev /mnt/dev\n# mount --rbind /proc /mnt/proc\n# mount --rbind /sys /mnt/sys\n# chroot /mnt /bin/bash --login\nRun Code Online (Sandbox Code Playgroud)\n注意:这是使用 --rbind,而不是 \xe2\x80\x94bind。
\n4.1 检查通配符获取正确的根池分区:
\n# for i in /dev/disk/by-id/*ata*part3; do echo $i; done\nRun Code Online (Sandbox Code Playgroud)\n4.2 将每个磁盘的 /boot/efi 条目添加到 /etc/fstab 以便将来进行故障转移:
\n# for i in /dev/disk/by-id/*ata*part3; \\\n do mkdosfs -F 32 -n EFI ${i}; \\\n echo PARTUUID=$(blkid -s PARTUUID -o value \\\n ${i}) /boot/efi vfat defaults 0 1 >> /etc/fstab; done\nRun Code Online (Sandbox Code Playgroud)\n4.3 挂载第一块磁盘
\n# mount /dev/disk/by-id/scsi-SATA_disk1-part3 /boot/efi\nRun Code Online (Sandbox Code Playgroud)\n4.4 安装grub
\n# grub-install --target=x86_64-efi --efi-directory=/boot/efi \\\n --bootloader-id=ubuntu --recheck \xe2\x80\x94no-floppy\nRun Code Online (Sandbox Code Playgroud)\n4.5 卸载第一个分区
\n# umount /boot/efi\nRun Code Online (Sandbox Code Playgroud)\n4.6 挂载第二块磁盘
\n# mount /dev/disk/by-id/scsi-SATA_disk2-part3 /boot/efi\nRun Code Online (Sandbox Code Playgroud)\n4.7 安装grub
\n# grub-install --target=x86_64-efi --efi-directory=/boot/efi \\\n --bootloader-id=ubuntu-2 --recheck \xe2\x80\x94no-floppy\nRun Code Online (Sandbox Code Playgroud)\n4.8 对每个附加磁盘重复步骤 4.5 到 4.7\n4.9 为了增加保险性,也对每个磁盘执行 MBR 安装
\n# grub-install /dev/disk/by-id/scsi-SATA_disk1\n# grub-install /dev/disk/by-id/scsi-SATA_disk2\nRun Code Online (Sandbox Code Playgroud)\n5.1 退出chroot
\n# exit\nRun Code Online (Sandbox Code Playgroud)\n5.2 重启
\n# reboot\nRun Code Online (Sandbox Code Playgroud)\n