大约三年前,我购入了人生第一台实体服务器——HP ProLiant MicroServer Gen8。当时的有些选择在现在看来并不是最优的,于是我在 2019 年初对 Gen8 进行了一些软硬件改造。

一、光驱位磁盘问题

Gen8 一共 4 个 3.5 英寸 SATA 硬盘盘位,但总共有 5 个 SATA 接口,第 5 个 SATA 接口在主板上的标记为「SATA - ODD」,原意是接光驱用,但广大 Gen8 用户(甚至包括后来的 Gen10 用户)纷纷选择把这个接口用于接第 5 块硬盘——通常是 2.5 英寸的 SSD。由于 SSD 并不惧怕震动,接好之后往光驱位随便一放即可,当然也可以用双面胶或电工胶带稍微固定一下。

我刚购入 Gen8 的时候,因为种种原因,未使用 SATA 5,而是把 SATA 1 的背板拆了下来,拉到顶上,接了个 2.5 英寸 SSD;从 SATA 2 开始才是接 3.5 英寸 HDD——这相当于浪费了一个 3.5 英寸的盘位。随着数据量的增加,我希望能将 4 个 3.5 英寸盘位全部利用起来,于是就想着把 SSD 移至 SATA 5。

要想让 SSD 工作于 SATA 5,需要解决供电问题。HPE 不知为何,只预留了一个小 4pin 的电源线(常用于软驱),而 SATA 硬盘用的是 15pin 的供电,这两者之间是没有标准转换线的。解决思路有:

  • 用两条转换线,先把小 4pin 转成大 4pin,再把大 4pin 转成 15pin;
  • 用一转二的 15pin 电源线,把别的 SATA 的供电线分出来给它用。

但大约是有这样需求的用户太多了吧,〇宝上可以买到专门的「Gen8 数据线」,有三个接口,一头接主板上的 SATA 接口,一头接光驱位预留的小 4pin 电源,还有一头直接连到 SATA 的电源/数据接口。

最后成功接上的效果是这样:

IMG_20190215_230135

简洁又美观。

二、AHCI 模式下的引导问题

Gen8 还有一个怪异点,那就是在 AHCI 模式下无法从任意 SATA 接口引导。

Gen8 是内置一个 B120i RAID 控制器的,但这其实是 Fake RAID,对操作系统不透明,需要加载额外的专有驱动才能使用。此外,为了能让每块硬盘能单独拔下来插到别的电脑上访问其中的内容,我也不会采用 RAID 方案的。从 Gen8 买回来的那天起我就没有启用 RAID 控制器,而是将其配置为 AHCI 模式。

在 AHCI 模式下,Gen8 可以选择从 SATA 控制器引导,但只能从第一个插了盘 SATA 接口引导。比如,四个 3.5 英寸盘位(SATA 1 至 SATA 4)都是空着的情况下,如果 SATA 5 接了一块引导盘,那么 SATA 5 里的系统是可以成功启动的;但如果 SATA 1 至 SATA 4 中的任何一个接口已经接了一块硬盘(不可引导的数据盘),那么 Gen8 就会尝试从那一块硬盘引导——引导失败,并且不再继续尝试后续硬盘。这一怪异点的常见应对方法有:

  • 放弃 AHCI,屈服于 B120i 的淫威,配置 Fake RAID,然后就可以从 SATA 5 所在的 RAID 阵列引导了;
  • 将系统装在 U 盘或 microSD 卡里(主板上有一个 USB 和一个 microSD 接口),然后在 BIOS 里选择从 USB 引导。

之前我是采取第二种方法。当时我的 Gen8 上装的系统是 VMware ESXi,这一系统只在启动的时候读取文件,之后都是纯内存运行,几乎不再进行写入操作,所以挺适合安装在脆弱的 microSD 卡里的。但我现在换了 Proxmox VE,这是一个基于 Debian Linux 的操作系统,是会有很多日志写入的,装在 U 盘或 microSD 卡里的话,很快就会把 U 盘或 microSD 卡写坏。

然后我有了一个大胆的想法,并实践了一下,发现可行。那就是:用 GRUB 二次引导。

三、使用 GRUB 引导 SATA 5 中的系统

计算机的引导过程,无非就是 BIOS / UEFI 去读取指定硬盘的头部(MBR / GPT),执行引导程序(GRUB、SYSLINUX 等),再由引导程序再去加载操作系统。现在既然 Gen8 不愿意直接从 SATA 5 引导,那么我们就让引导程序去找 SATA 5 好了。

GRUB 是个复杂而又功能强大的引导程序,支持各种文件系统,甚至是 LVM 和 LUKS 等复杂结构,很适合来完成这个「二传」的事情。本文的 GRUB 是指 GRUB 2。

安装 GRUB

取一张空白 microSD 卡或一只空白的 U 盘(我直接拿之前装 ESXi 的那张了),插到任意一台 GNU/Linux 机器上(虚拟机应该也行),开始操作。

# 执行以下命令前,请先使用你最爱的包管理器安装 gdisk 和 grub

# 擦除已有 MBR / GPT,请先用 lsblk 确认 microSD 卡的名字,此处为 /dev/sdb
$ sudo sgdisk -Z /dev/sdb

# 新建两个分区,一个 2 MiB 的 BIOS boot partition,一个 512 MiB 的 EFI System
$ sudo sgdisk -n 1:0:+2M -t 1:ef02 -n 2:0:+512M -t 2:ef00 /dev/sdb

# 格式化 EFI 分区
$ sudo mkfs.vfat /dev/sdb2

# 挂载 EFI 分区
$ sudo mount /dev/sdb2 /mnt

# 新建 boot 目录(用于安装 GRUB)
$ sudo mkdir /mnt/boot

# 将 GRUB 安装到 microSD 卡里
$ sudo grub-install --boot-directory /mnt/boot /dev/sdb

至此 GRUB 已经被安装到 microSD 里了。但是我们还没有配置文件。GRUB 本身提供了 grub-mkconfig 工具可以用来生成一个适用于当前系统的配置文件,但这并不是我们想要的,所以我们需要手写一个。

配置 GRUB

根据你安装 GRUB 时的发行版,GRUB 可能被安装到了 /mnt/boot/grub 或是 /mnt/boot/grub2 目录里,这不重要;其配置文件 grub.cfg 就在这个目录里。使用你最喜爱的编辑器打开 grub.cfg 文件(新文件),参考 GRUB 文档,增加类似这样的条目:

set timeout=5

menuentry 'Load Proxmox VE grub.cfg' {
        insmod part_gpt
        insmod lvm
        insmod ext2
        set root='lvmid/jfwkcN-crbm-WWJc-jpWT-0Tif-mpIW-RIPmN7/OK06r0-BiRx-6a3R-NnZZ-dbZC-0Urx-w0uEPe'
        configfile /boot/grub/grub.cfg
}

其中 insmod 的作用是加载必要的模块(比如要读取 LVM 卷里的数据,就要加载 lvm 模块);set root 是指定根目录(/)所在的分区/卷(相当于挂载);最后 configfile 指示 GRUB 去加载根目录里另一个 grub.cfg(属于 Proxmox VE)配置。

更新:应读者询问补充说明:上述配置中 root= 后面的 lvmid 可通过 lvdisplay 命令获取。

完整的引导过程是这样:

  1. Gen8 的 BIOS 试图从 microSD 引导,成功执行 microSD 上的引导程序(GRUB);
  2. GRUB 根据 microSD 上 grub.cfg 文件中的信息,凭借 LVM UUID 定位到 SATA 5 上的 Proxmox VE 分区,并读取其中的 grub.cfg 文件;
  3. GRUB 根据新的配置文件重新加载自身,并根据新文件中的配置加载操作系统(Proxmox VE)。

这一过程中涉及到了两个引导程序,都是 GRUB。但第二个引导程序可以是别的,比如对于 Windows,可以使用 ntldr /bootmgr 来执行 Windows 的引导程序;你也可以使用 chainloader +1 来将控制权交给任意其他引导器。

上面的例子中使用了 LVM ID 来定位第二个引导程序所在的分区/卷,你也可以用 search 命令,凭借文件系统的 UUID 或卷标来定位(这些信息可以用 lsblkgrub-probe 找到)。比如这是一个引导安装在 MBR 分区里的 Windows 10 的例子(真的有人在 Gen8 上安装 Windows 10 吗?):

menuentry "Windows 10" {
        insmod part_msdos
        insmod ntfs
        insmod ntldr
        search --fs-uuid --set=root 2ABF87DC395CFC02
        ntldr /bootmgr
}

更多的例子可以参考 ArchWikiGentoo Wiki

引导!

将制作好的 microSD 插入 Gen8 主板,在 BIOS 中选择从「USB Key」启动,重启。在 POST 之后,可以看到 microSD 里的 GRUB 的菜单,有且只有一条选择,那就是我们刚才手写的加载另一个引导程序的条目。若不做任何操作,则在 5 秒后(由 set timeout 决定)自动选择,然后你就能看到第二个引导程序的界面了。

在 microSD 制作完成之后,就不会再有写入了,且 microSD 上的 GRUB 也只在 Gen8 启动时读取一次,进入操作系统之后就不再读取(你甚至可以把它拔下来——当然记得下次启动的时候插回去),就算是脆弱的 microSD 卡,也应该能用很久。

本文地址: https://wzyboy.im/post/1306.html


欢迎留下评论。评论前,请先阅读《隐私声明》。