适用场景:服务器主板不能从 PCIe NVMe 启动,但 PVE 已经装在 NVMe 上。你不想刷 BIOS,也不想重装系统,只想让它正常开机。
先说结论:用一块 U 盘承载 rEFInd 和 NVMe DXE 驱动,开机时由 U 盘“看见”NVMe,再把启动权交给 NVMe 上的 PVE GRUB。U 盘可以长期插在服务器内部,内核升级也不需要重做。
整套方案的核心不是“绕过固件”,而是在固件和 PVE 之间补上一个自带 NVMe 驱动的小型引导环境。
一、问题:系统装得上,为什么启动不了?
很多人第一次遇到这个问题,会以为是“主板完全不认 NVMe”。其实不是。
典型现场是这样的:
- PVE 安装器里,NVMe 清清楚楚地列着,安装一切正常;
- 安装完成重启,BIOS 启动菜单里却找不到这块盘;
- 启动顺序里只有 SATA、USB、网络,没有
UEFI: NVMe...。
原因在于两个阶段使用的驱动不是同一套:
| 阶段 | 谁在访问 NVMe | 结果 |
|---|---|---|
| 安装 / 进入 Linux 后 | Linux 内核自带的 nvme 驱动 |
能识别、能分区、能安装 |
| 开机选启动项时 | 主板 UEFI 固件 | 固件没有 NVMe DXE 驱动,看不到盘 |
UEFI 固件要通过 DXE(Driver Execution Environment) 驱动来识别存储控制器。老平台可能只带了 SATA、USB、AHCI 的 DXE,没有 NvmExpressDxe。固件看不到 NVMe,自然也不会把它列进启动菜单。
所以问题的本质是:固件缺少一个能在启动阶段访问 NVMe 的驱动。
二、PVE 默认布局里的一个死结
要理解为什么不能“让 rEFInd 直接启动内核”,先看 PVE 默认把盘分成了什么样。

典型的 PVE UEFI 安装(ext4 + LVM)会得到三块分区:
| 分区 | 大小 | 作用 |
|---|---|---|
p1 |
1 MB | BIOS boot,传统 GRUB 的遗留区域 |
p2 |
512 MB | EFI System Partition(ESP),FAT32,存放 EFI/proxmox/grubx64.efi 和 grub.cfg |
p3 |
剩余空间 | LVM PV,里面是 pve-root、pve-swap 等逻辑卷 |
关键在于:PVE 默认把 /boot 也放在 pve-root 这个逻辑卷里,而不是单独分一个 /boot 分区。
于是形成两个事实:
- rEFInd 能读 p2。 它自带 FAT 驱动,能读取 ESP 上的 GRUB 文件。
- rEFInd 读不了 p3。 它的
drivers_x64里有 ext2/ext4/btrfs 等文件系统驱动,但没有 LVM 驱动。逻辑卷不是普通分区,rEFInd 无法把pve-root当成文件系统挂起来。
死结就在这里:
rEFInd 想直接找内核
↓
内核在 /boot
↓
/boot 在 pve-root 逻辑卷里
↓
rEFInd 没有 LVM 驱动,读不到
这也解释了一个常见误区:在 U 盘根目录放一个 refind_linux.conf,并不能让默认 PVE 直接启动。rEFInd 是在“内核所在目录”里找这个文件的;它连 /boot 都进不去,自然不会读到你放在 U 盘根目录的那份配置。
三、跳板盘的启动链路
既然 rEFInd 读不了 LVM,就不要让它读。让它把“接力棒”交给一个能读 LVM 的引导器——PVE 自己的 GRUB。

完整链路是:
服务器 UEFI 固件
│ 只认 FAT32,加载 U 盘的 \EFI\BOOT\BOOTX64.EFI
▼
U 盘上的 rEFInd
│ 从 drivers_x64 加载 nvme_x64.efi
▼
NVMe DXE 驱动生效
│ 固件此时能看见 NVMe 控制器和分区
▼
NVMe ESP 上的 PVE GRUB
│ \EFI\proxmox\grubx64.efi,读取自己的 grub.cfg
▼
LVM 里的 /boot 与内核
│ /dev/mapper/pve-root → /boot/vmlinuz-*
▼
PVE 启动
几个设计上的关键点:
- U 盘只负责“看见 NVMe”。 它不承载内核,也不参与内核升级。
- GRUB 从 NVMe ESP 上执行,而不是复制到 U 盘。 GRUB 的
grubx64.efi有自己的 prefix 和模块路径,复制到 U 盘后很可能找不到配置和模块;在原位执行则保持它熟悉的环境。 - 内核升级由 PVE 自己维护。 每次升级后,PVE 会更新 ESP 上的引导配置(GRUB 的
grub.cfg,或 systemd-boot 的loader/entries);rEFInd 只是每次把控制权交过去,不需要改任何东西。 - U 盘可以长期插在服务器内部 USB 口。 只要 BIOS 启动顺序把
UEFI: <U盘>放在第一位,重启就不需要每次按 F11。
这就是“零维护”的含义:不是永远不坏,而是内核升级、GRUB 更新都不需要重新制作跳板盘。
四、工具如何自动完成
整个 Windows 工具可以分成四段:探测、决策、写入、校验。

4.1 探测:先把事实读准
工具不靠分区大小猜,而是用 GPT 类型 GUID 识别分区:
$EspTypeGuid = 'c12a7328-f81f-11d2-ba4b-00a0c93ec93b'
$LvmTypeGuid = 'e6d6d379-f507-44c2-a23c-238f2a3df928'
$LinuxFsTypeGuid = '0fc63daf-8483-4772-8e79-3d69d8477de4'
$BiosBootTypeGuid = '21686148-6449-6e6f-744e-656564454649'
这四个 GUID 分别对应 ESP、Linux LVM、Linux 文件系统、BIOS boot。磁盘列表里的 ESP+LVM 备注就来自这里。
如果 PVE 盘接在 Windows 上,工具会临时给 ESP 分配一个盘符,只读地找:
EFI\proxmox\grubx64.efi
EFI\proxmox\shimx64.efi
EFI\debian\grubx64.efi
EFI\systemd\systemd-bootx64.efi
EFI\BOOT\grubx64.efi
找不到时,还会检查 EFI\BOOT\BOOTX64.EFI 的内容里是否包含 GRUB 或 systemd-boot,最后递归找任意 grubx64.efi。读取完成后,临时盘符会被移除。
4.2 决策:生成链式启动配置
如果检测到 PVE 引导器,工具会生成类似下面的 refind.conf:
# Generated by PVE Jump Drive Tool
timeout 5
use_nvram false
scanfor internal,external,optical
also_scan_dirs boot
dont_scan_dirs EFI/refind
menuentry "Proxmox VE (NVMe GRUB)" {
volume 12345678-1234-1234-1234-123456789abc
loader \EFI\proxmox\grubx64.efi
}
default_selection "Proxmox VE (NVMe GRUB)"
每一项都有明确目的:
| 指令 | 作用 | 为什么这样设 |
|---|---|---|
timeout 5 |
菜单停留 5 秒 | 有可靠默认项时自动启动,失败也能手动选 |
use_nvram false |
不写 UEFI NVRAM | 跳板盘可能换口、换机器;不污染服务器启动项 |
scanfor internal,external,optical |
扫描内置、外置、光驱 | 兼容 NVMe、SATA、USB |
dont_scan_dirs EFI/refind |
不扫描第二份 rEFInd | 避免菜单出现重复条目 |
volume <GUID> |
指定加载器所在分区 | 用分区 GUID,不用会变的 fs0: |
loader <路径> |
要加载的 EFI 文件 | 指向 NVMe ESP 上的 PVE GRUB |
为什么用分区 GUID,而不是盘符?
UEFI 的卷编号在不同启动、不同插槽下会变化。今天 U 盘是 fs1:,明天可能是 fs0:。分区 GUID 跟着分区走,不跟着枚举顺序走。
为什么关闭 NVRAM 写入?
对一块可能随时拔走的 U 盘来说,把自己注册进服务器启动项没有必要,还可能留下一个指向“当前 USB 口”的失效条目。关闭后,启动完全依赖 BIOS 里的 UEFI: <U盘> 顺序,行为更可控。
4.3 写入:双份安装,双份驱动
工具会把 rEFInd 同时复制到两个目录:
EFI\BOOT\ ← UEFI 默认回退路径,BOOTX64.EFI 放这里
EFI\refind\ ← rEFInd 的常规目录,保留完整副本
原因很简单:
- 很多主板即使没有 NVRAM 条目,也会自动扫描
\EFI\BOOT\BOOTX64.EFI; EFI\refind是 rEFInd 的“家目录”,配置、图标、字体、驱动都在这里更符合习惯;- 两个目录都放一份
drivers_x64,因为 rEFInd 是从“自己所在目录”加载驱动的。
NVMe 驱动也因此在两处各放一份:
Copy-Item -LiteralPath $NvmeDriver `
-Destination (Join-Path $bootDrivers 'nvme_x64.efi') -Force
Copy-Item -LiteralPath $NvmeDriver `
-Destination (Join-Path $refindDrivers 'nvme_x64.efi') -Force
少任何一份,都可能出现“从一个入口启动能看到 NVMe,从另一个入口看不到”的诡异现象。
4.4 校验:不给自己“成功的假象”
制作完成后,工具会逐一检查 8 个关键文件是否存在且非空:
EFI\BOOT\BOOTX64.EFI
EFI\BOOT\refind.conf
EFI\BOOT\drivers_x64\nvme_x64.efi
EFI\BOOT\drivers_x64\ext4_x64.efi
EFI\refind\refind_x64.efi
EFI\refind\refind.conf
EFI\refind\drivers_x64\nvme_x64.efi
refind_linux.conf
少一个就报错,不会打印“制作成功”。日志会写到工具目录,并复制一份到 U 盘根目录的 tool-log.txt。
五、三个安全设计,避免“选错盘”
下面的代码是工具里的关键片段,省略了错误处理和兜底分支;完整实现见
Make-PveRefindUsb.ps1。
分区工具最怕误操作。这个工具在写入前加了几道闸:
- 跳板盘必须是 USB,不能是 Windows 系统盘,不能和 PVE 系统盘相同,也不能是工具自己所在的盘。
- 必须输入
ERASE才会清空;其他任何输入都取消。 - 写入前再复核一次总线类型、容量和序列号:
$fresh = Get-Disk -Number $jump.Number
if ($fresh.BusType -ne 'USB') { throw '跳板盘不再是 USB 磁盘,已中止。' }
if ([uint64]$fresh.Size -ne [uint64]$jump.Size) { throw '磁盘容量发生变化,已中止。' }
if ($jump.SerialNumber -and $fresh.SerialNumber -and
($fresh.SerialNumber -ne $jump.SerialNumber)) {
throw '磁盘序列号发生变化,已中止。'
}
从选择磁盘到输入 ERASE 之间,用户可能拔插了设备,Windows 也可能重新编号。只靠最初读到的对象是不够的。
另外,工具支持 -DryRun:不写任何磁盘,只在 .\dryrun\ESP 生成文件,用来检查目录结构和配置内容。
六、制作步骤
6.1 准备
| 项目 | 要求 |
|---|---|
| Windows | Windows 10/11 x64,PowerShell 5.1+ |
| 权限 | 管理员 |
| 跳板 U 盘 | ≥ 1 GB,建议 4 GB+,会被完全清空 |
| PVE 系统盘 | 建议通过 USB 转接盒接入,仅用于只读识别 |
| 服务器 | UEFI 启动,可关闭 Secure Boot |
把 PVE 的 NVMe 接到 Windows 时,资源管理器可能提示“需要格式化磁盘”。不要格式化,不要初始化,点取消。工具只读它的 ESP 分区。
工具在启动时只枚举一次磁盘。请先把 PVE 盘和 U 盘都接好,再运行。
6.2 运行
双击项目根目录的:
制作PVE跳板盘.cmd
它会自动请求管理员权限,然后调用同目录下的 Make-PveRefindUsb.ps1。
工具会列出磁盘,例如:
编号 总线 大小 型号 分区表 备注
--------------------------------------------------------------------------------
0 NVMe 1.86 TB Predator SSD GM7 2TB GPT Windows系统盘-禁止
1 USB 1.82 TB WD Blue SN5000 (USB转接) GPT USB,ESP+LVM
2 USB 28.9 GB SanDisk Ultra USB 3.0 GPT USB
Windows系统盘-禁止:绝对不能选;USB,ESP+LVM:很像 PVE 系统盘(可能是 USB 转接的 NVMe);- 只有
USB的:通常是跳板 U 盘。
6.3 选择与确认
- 选择 PVE 系统盘(输入编号;输入
S可跳过;直接回车使用默认建议); - 选择 跳板 U 盘(必须是 USB,会被清空);
- 输入
ERASE确认; - 等待完成。
完成后会看到:
[+] ESP 就绪:G: FAT32 1,020.0 MB
[+] 关键文件校验通过:8 项
[+] 跳板盘:G: FAT32 / REFIND
[+] 链式启动项:Proxmox VE (NVMe GRUB) -> \EFI\proxmox\grubx64.efi
拔盘前使用 Windows 的“安全删除硬件”。
七、服务器端启动
- 关机,把跳板 U 盘插到服务器 USB 口(优先主板内部 USB 口,长期插着)。
- 开机按
F11/F12/F8进入启动菜单。 - 选择
UEFI: <U盘名称>,不要选 Legacy/BIOS。 - 在 rEFInd 菜单里选择
Proxmox VE (NVMe GRUB)。 - 如果菜单里没有这一项,选择自动扫描到的
grubx64.efi、systemd-bootx64.efi或 Proxmox 条目。
BIOS 里建议确认:
| 设置 | 建议值 | 原因 |
|---|---|---|
| Boot Mode | UEFI | Legacy/CSM 读不到 U 盘的 UEFI 引导文件 |
| Secure Boot | Disabled | rEFInd 和 NVMe DXE 驱动未签名 |
| USB Boot | Enabled | 允许从 U 盘启动 |
| Boot Order | UEFI: <U盘> 第一 |
重启不用每次按 F11 |
| PCIe Slot Mode | EFI/UEFI(如果有) | 让固件愿意枚举 NVMe |
长期使用建议把 UEFI: <U盘> 放在启动顺序第一位。U 盘可以一直插在内部 USB 口,不影响 PVE 读写 NVMe。
八、如果 /boot 是独立分区
默认方案是链式启动,适合 /boot 在 LVM 里的 PVE。但如果你的 /boot 是独立 ext4 分区,还可以让 rEFInd 直接引导内核。

/boot 的位置,再决定用哪种启动方式。在 PVE 里执行:
findmnt /boot
| 输出 | 结论 | 下一步 |
|---|---|---|
/dev/mapper/pve-root[/boot] |
/boot 在 LVM 里 |
什么都不用做,链式启动已经工作 |
/dev/nvme0n1p2 |
独立 /boot 分区 |
可以复制 refind_linux.conf,启用直接引导 |
只有 BIOS boot + LVM,没有 ESP |
Legacy 安装 | 链式启动不可用,需要独立 /boot 或重装 UEFI |
如果 /boot 是独立 ext4 分区,把 U 盘根目录的 refind_linux.conf 复制到 /boot:
mkdir -p /mnt/usb
mount /dev/sdX1 /mnt/usb # 把 sdX1 换成 U 盘分区
cp /mnt/usb/refind_linux.conf /boot/refind_linux.conf
umount /mnt/usb
也可以直接运行 U 盘上的脚本:
sh /mnt/usb/install-refind_linux_conf.sh
之后 rEFInd 菜单会直接列出内核,内核升级后自动出现新版本。
如果
/boot在 LVM 里,不要做这一步,做了也不会生效。
九、常见问题
9.1 启动菜单里没有 U 盘
- 服务器是否处于 UEFI 模式,而不是 Legacy/CSM;
- BIOS 是否启用了 USB Boot;
- Secure Boot 是否关闭;
- U 盘是否是 GPT + FAT32(工具会做);
- 换一个 USB 口,优先主板后置/内部 USB;
- 有些服务器需要在 BIOS 里把 USB 设备设为 UEFI。
9.2 有 rEFInd,但菜单里没有 PVE
- 确认 PVE 盘 ESP 里有
EFI/proxmox/grubx64.efi、EFI/debian/grubx64.efi或EFI/systemd/systemd-bootx64.efi; - 确认 U 盘
EFI/BOOT/drivers_x64/nvme_x64.efi和EFI/refind/drivers_x64/nvme_x64.efi都存在; - 确认 BIOS 能枚举 PCIe NVMe(有些平台需要把 PCIe 插槽设为 EFI/UEFI 模式);
- 如果 PVE 是 Legacy 安装,根本没有 ESP,rEFInd 无法链式启动。
9.3 选择 PVE 后黑屏 / GRUB 报错
先在能启动的 PVE 环境里重新生成 GRUB,确保 core 镜像包含 nvme、lvm、ext2:
grub-install --target=x86_64-efi \
--efi-directory=/boot/efi \
--bootloader-id=proxmox \
--modules="nvme lvm ext2 part_gpt"
update-grub
如果是 systemd-boot 方案(常见于 ZFS 根),改用:
proxmox-boot-tool status
proxmox-boot-tool refresh
9.4 内核启动到 initramfs 后找不到根
检查 initramfs 是否包含 NVMe / LVM:
lsinitramfs /boot/initrd.img-$(uname -r) | grep -E 'nvme|dm-mod|lvm'
缺少时:
echo nvme >> /etc/initramfs-tools/modules
echo dm-mod >> /etc/initramfs-tools/modules
update-initramfs -u -k all
9.5 根设备不是 /dev/mapper/pve-root
工具会优先从 grub.cfg 读取 root=;读不到时默认 /dev/mapper/pve-root。如果你的 VG/LV 名不同,重新制作时指定:
.\Make-PveRefindUsb.ps1 -RootDevice /dev/mapper/你的VG-你的LV
ZFS 根则用:
.\Make-PveRefindUsb.ps1 -RootDevice ZFS=rpool/ROOT/pve-1
链式启动时,
root=由 PVE 自己的grub.cfg决定;这个参数只影响直接内核引导。
十、边界与安全
这套方案不是万能的,先确认边界:
| 限制 | 影响 | 规避 |
|---|---|---|
| 仅 x64 UEFI | 32 位 UEFI/ARM 不可用 | 换平台或找对应架构引导器 |
| Secure Boot 必须关闭 | 强制签名环境不能直接用 | 关闭 Secure Boot,或自行签名 |
| 固件必须能枚举 NVMe | 极老平台可能无解 | 升级 BIOS、调整 PCIe 模式、换平台 |
| Windows 不能写 ext4/LVM | 独立 /boot 的配置要进 PVE 复制 |
按第八节操作一次 |
| 不修改 PVE 的 GRUB | 链式启动依赖 PVE 自己的引导器 | 如果 PVE GRUB 损坏,先修 PVE |
| U 盘会被清空 | 数据不可恢复 | 选盘时确认容量/型号,提前备份 |
安全提醒:跳板 U 盘会被完全清空;工具对 PVE 系统盘只做只读检查,但任何磁盘操作都有风险。第一次使用建议在可停机的测试环境验证,生产环境先备份 PVE 配置和虚拟机数据。
十一、小结
- 问题不是 NVMe 坏了,而是固件缺少启动阶段的 NVMe 驱动。
- PVE 默认把
/boot放在 LVM 里,而 rEFInd 不能读 LVM,所以用链式启动,让 PVE 自己的 GRUB 接管。 - U 盘只负责“看见 NVMe”,内核升级由 PVE 维护,跳板盘不需要跟着重做。
- 只有
/boot是独立 ext4 分区时,才需要复制refind_linux.conf做直接引导。 - 制作时务必确认磁盘型号和容量,输入
ERASE前再检查一遍。
如果这篇文章帮你救回了一台“不能从 NVMe 启动”的服务器,欢迎把踩过的坑补充在评论里。
主题测试文章,只做测试使用。发布者:zy,转转请注明出处:https://zynetc.top/?p=2026102709