PXE 网络批量装机实战:TinyPXEServer 配置与排错
发布时间:2026/9/17 3:04:30 锦皓数字建站

上个月帮一家做产线检测设备的朋友收拾机房的烂摊子三十多台工控机要统一换成同一套 Windows 镜像还要在其中三台上顺带装一套 Linux 做数据采集。机房在地下室没有机柜机器就堆在货架上一台一台插 U 盘装光是拔插和等待就得耗掉两个通宵。我当时提了个方案搭一个 PXE 网络引导环境把机器全部改成网卡启动按一下电源键剩下的交给网络。朋友的第一反应是这玩意儿是不是得装一堆服务配不好网络就全废了这也是大多数人对 PXE 网络批量安装操作系统的固有印象。实际做过一次就知道真正麻烦的不是原理而是那些散落在各个角落的细节DHCP 选项 66 和 67 到底填什么、UEFI 和 Legacy BIOS 为什么不能共用一套引导文件、WinPE 加载到一半提示找不到网卡、几十台机器同时拉镜像时 TFTP 直接卡死。这篇就把我用 TinyPXEServer 这套小工具做网络批量装机的完整过程摊开讲从网络拓扑怎么选、目录怎么摆、引导文件怎么备到无人值守应答文件怎么写、报错怎么排查。适合手上有十几到上百台机器要部署、又没有成套自动化运维平台的场景也适合想搞明白 PXE 到底是怎么跑起来的技术同学。1. 为什么我最后选了 TinyPXEServer而不是在 Linux 上折腾 dnsmasq1.1 PXE 装机的三段式链路DHCP 派地址、TFTP 递引导、镜像走文件服务PXE 这个东西第一次接触会觉得玄乎拆开看其实只有三个环节首尾相接。客户端网卡上的 PXE ROM 在开机时先广播一个 DHCP 请求这个请求和普通上网要地址的请求长得不一样它带了一段厂商扩展信息大意是在说我不光要 IP我还要一个能启动的东西。第一段链路就是响应这个请求把 IP 地址、网关、DNS 连同去哪台机器拿引导文件引导文件叫什么名字一起发回去。第二段链路是客户端拿着返回的地址和文件名用 TFTP 协议去把那几百 KB 到几 MB 的引导程序拉回本地内存执行。第三段链路才是引导程序接管之后的事它去读取菜单、加载内核或者 WinPE 镜像这个阶段的数据量是几百 MB 级别用 TFTP 拉会非常痛苦所以通常换成 HTTP。理解这三段之后很多玄学问题就有了归处。比如提示拿不到引导文件名问题在第一段提示 TFTP 超时问题在第二段引导菜单出来了但加载镜像卡住问题在第三段。我后来的排查习惯就是先看进度条走到了哪一步再决定去查哪个环节。网络批量安装操作系统的本质是把介质从 U 盘换成了网卡。U 盘装机的流程是插盘、读盘、写盘、拔盘、下一台。PXE 把它变成了开机、等待、重启、下一台。省掉的是人工拔插和值守但换来的代价是你要提前把网络、引导、应答文件这三块都准备好而且一旦配错影响的不是一台而是一整个网段。1.2 那些重方案在什么场景下反而拖后腿做批量部署网上一搜基本都是两条路一条是 Windows 侧的 WDS 加 MDT另一条是 Linux 侧的 dnsmasq 加 tftp-hpa 加 nginx 加 syslinux 全家桶。这两条路都很成熟功能也远比小工具强但它们的门槛在具体场景里会被放大。WDS 需要域环境或者至少一台 Windows Server装完角色还要配 WDS 的引导映像、安装映像、应答文件部署一台服务器本身的成本就比要装的机器还高。MDT 更重任务序列、驱动库、数据库学习曲线陡得吓人。如果是给公司做长期标准化运维这套投入是值的但如果只是临时把三十台机器刷成同一个镜像投进去的时间根本收不回来。Linux 那套组合拳的问题在依赖。dnsmasq 需要改配置、处理端口冲突、注意和系统里已有的 DHCP 客户端打架tftp-hpa 的根目录权限、SELinux 策略、防火墙规则每一样都能让人卡半天。更麻烦的是这套环境搭在 Linux 上而你要装的往往是 Windows中间还得跨系统共享镜像文件路径和权限又是一轮折腾。我最后选 TinyPXEServer理由很朴素单个绿色程序双击就能跑DHCP、ProxyDHCP、TFTP、HTTP 四个服务全在里面配置文件就是一个ini随时拷走换机器。对于一周之内把几十台机器刷完然后拆掉这类一次性任务它的性价比高得离谱。1.3 TinyPXEServer 的能力边界以及它做不了的事用得顺手不代表它是万能的恰恰相反越小的工具边界越清晰。它擅长的是在已经有网络的环境里快速提供一个 PXE 引导入口把客户端引到引导文件上再把镜像通过 HTTP 分发出去。它不擅长的是精细化的 DHCP 管理比如租约保留、按 MAC 分配固定 IP、多网段地址池这些也不提供并发调度不会因为你同时来五十台客户端就自动分配带宽更没有任务序列引擎装完系统之后自动装软件、加域、跑脚本这些事得靠应答文件或者装完之后的脚本。我的做法是把它当成一个引导跳板而不是完整方案。真正复杂的后置动作我放在镜像里的首次启动脚本中执行让系统自己装完之后拉一个批处理下来跑。这样工具的边界和工作的边界就对齐了不会硬塞给它不该干的活。还有一点需要提前说清楚TinyPXEServer 界面上的功能是有限的更多时候我是先用界面把服务跑通然后再去改 ini 文件加细节。改的时候要留个备份有些字段写错会导致程序启动直接报错而不是给你一个友好的提示。2. 动手之前先把网络这层想明白2.1 单网段直连最省事的拓扑如果你的待装机器和跑 TinyPXEServer 的机器在同一个二层网络里中间没有三层设备那事情简单得超乎想象。把服务端机器的有线网卡设一个固定 IP比如 192.168.10.1掩码 255.255.255.0然后在这个网卡上开 TinyPXEServer 的 DHCP 服务地址池设成 192.168.10.100 到 192.168.10.200网关和 DNS 都指向 192.168.10.1。这里有一个容易忽略的点服务端机器如果同时连着公司的办公网它就有两块网卡而你肯定不希望 TinyPXEServer 的 DHCP 去给办公网发地址。程序里一般有一个绑定网卡或者绑定 IP 的选项一定要选成那块专门用于装机的网卡。我在第一次做的时候忘了这回事结果整个办公区断网两分钟场面相当尴尬。拓扑上建议待装机器和服务端之间用一个独立的小交换机不要和生产网混在一起。独立交换机有两个好处一是广播域干净PXE 的广播包不会外泄二是真的出问题的时候拔掉一根线就能把影响范围控制住。2.2 网络里已经有 DHCP 服务器怎么办ProxyDHCP 模式更常见的情况是待装机器所在的网段本来就有一个 DHCP 服务器在工作可能是路由器也可能是核心交换机上跑的服务。这时候如果 TinyPXEServer 也开普通 DHCP两个服务器抢着发地址客户端的表现就是时好时坏一会儿能进 PXE一会儿进不去排查起来极其费神。正确的做法是启用 ProxyDHCP 模式我通常叫它代理启动模式。开启之后TinyPXEServer 不再负责分配 IP 地址地址仍然由原有 DHCP 服务器发它只负责回答客户端那个我去哪拿引导文件的问题。这个模式的好处是零侵入不会动到现有网络的地址分配装完机器关掉程序就完事。要注意的是这种模式下原有的 DHCP 服务器不能禁用 PXE 相关的响应选项也不能屏蔽客户端的广播。有些路由器的 DHCP 设置里会有一个禁止未知 PXE 客户端之类的开关需要确认一下。我在一次实施中就遇到过某品牌路由器默认丢弃带厂商扩展的 DHCP 请求导致 ProxyDHCP 完全收不到客户端的广播把那个选项关掉之后立刻正常。如果原有 DHCP 服务器和服务端不在同一个二层网络那还需要在中间的三层设备上配置 DHCP 中继让它把广播转成单播投递过来。这一步已经超出了小工具的范围属于网络层面的配置提前和网管沟通好比较省事。2.3 Legacy BIOS 与 UEFI同一批机器可能需要两套引导文件这是新手最容易翻车的地方。Legacy BIOS 和 UEFI 是两套完全不同的固件引导规范它们对引导文件的要求也不一样。Legacy 时代网卡 ROM 找的是像 pxelinux.0 这样的二进制程序UEFI 时代找的是 .efi 结尾的可执行文件比如 bootx64.efi 或者 iPXE 的 efi 版本。两者之间不能互换。麻烦的是现实场景里往往是混着的。老一点的工控机、收银机、瘦客户机基本都是 Legacy新买的笔记本、迷你主机基本都是 UEFI有些主板还同时支持两种靠一个开关切换。如果只准备了一套引导文件那另一半机器就会卡在找不到启动文件的阶段。我的处理办法是在 DHCP 的启动文件名配置里区分两类客户端。TinyPXEServer 这类工具通常允许你在引导文件名那一栏填一个委托文件让引导程序自己根据架构决定加载哪个。iPXE 就支持这种做法它的 .pxe 版本被加载之后可以判断自己运行在什么固件环境下再去拉对应的 .efi 或者 .kpxe。另一条路是干脆把启动文件名留空让客户端通过 PXE 的架构标识选项去分别匹配不过这需要 DHCP 服务端支持按选项值分流小工具不一定做得到。最省心的办法其实是引导程序套引导程序无论 Legacy 还是 UEFI 都先加载 iPXE然后在 iPXE 的脚本里判断环境再加载对应的下一级引导器。这样 DHCP 那层只需要配一次。3. TinyPXEServer 的各项配置逐条拆开讲3.1 装机目录长什么样TFTP 根、HTTP 根、引导文件该放哪TinyPXEServer 的目录结构是理解它的关键。程序文件夹里通常有几类东西可执行文件本身、一个 ini 配置文件、以及若干用于存放引导文件和镜像的子目录。不同版本目录命名可能略有差异但职责划分逻辑是一样的。TFTP 服务的根目录是客户端通过 TFTP 拉取文件时的根。比如客户端请求的文件名是 ipxe.pxe那这个文件就得放在 TFTP 根目录下面。PXE 客户端的请求文件名是不带路径的所以你在 DHCP 里配置的启动文件名要和实际存放的文件名严格一致大小写敏感的问题在某些 TFTP 客户端上也存在虽然多数 PXE ROM 不区分但我习惯统一用小写。HTTP 服务的根目录是给引导程序加载大镜像用的。比如 iPXE 脚本里写kernel http://192.168.10.1/boot/wimboot那 wimboot 这个文件就要放在 HTTP 根目录下的 boot 文件夹里。HTTP 根和 TFTP 根可以是同一个物理目录也可以是不同的目录我一般让它俩指向同一处减少文件重复拷贝的麻烦。目录规划上我习惯按引导层和镜像层分开。引导层放几个小文件几百 KB 到几 MB走 TFTP镜像层放 boot.wim、install.wim、ISO、initrd 这些大块头走 HTTP。分开之后排查也方便TFTP 出问题就只看引导层那几个文件。有一点要注意路径里尽量不要出现中文和空格。TFTP 和 HTTP 的路径解析在处理非 ASCII 字符时表现不一致轻则找不到文件重则直接报错。我给目录命名一律用英文加数字简单粗暴但从来没出过问题。3.2 DHCP 面板地址池、网关、DNS、启动文件名的填写逻辑打开 DHCP 面板通常要填这几项起始 IP、结束 IP、子网掩码、网关、DNS、启动文件名。每一项都有它的作用填错的后果也不一样。起始和结束 IP 划定了地址池范围。这个范围要和你的服务端 IP 在同一网段且不能包含服务端自己的地址。比如服务端是 192.168.10.1地址池可以设成 192.168.10.100 到 192.168.10.200留出前面一段给静态设备。地址池大小要大于同时开机的机器数注意 PXE 阶段的租约是短期的如果地址池太小先开机的机器还在装后开机的就分不到地址了。子网掩码不用多说网关和 DNS 在纯装机场景里其实不那么关键但有些引导程序会尝试解析域名填一个可用的 DNS 能避免一些奇怪的等待。我通常把网关和 DNS 都指向服务端自身服务端有没有真正联网并不影响装机因为所有文件都在本地。启动文件名是整个配置里最核心的一项。填的就是客户端要通过 TFTP 拉取的那个文件。填错了或者在 TFTP 根目录里找不到这个文件客户端就会报出没有收到启动文件名或者TFTP 打开超时的错误。不同引导方案这里填的东西不一样Legacy 加 PXELINUX 填 pxelinux.0Legacy 加 iPXE 填 ipxe.pxeUEFI 填 ipxe.efi 或者 bootx64.efi。还有一项容易被忽略的是租约时间。PXE 阶段希望租约短一点让装完的机器快速释放地址但如果租约太短装机过程中可能因为续租失败导致网络中断。我一般设成十几分钟到半小时之间比整个装机过程略长一点。3.3 大镜像别走 TFTPHTTP 通道的开启方式TFTP 这个协议诞生在上世纪八十年代设计目标是简单可靠不是快。它的传输单位默认是 512 字节一个块发一个包等一个确认网络稍有抖动就会重传。用它传几 MB 的引导程序还算能忍传一个 4 GB 的 install.wim 基本等于自虐。TinyPXEServer 内置了 HTTP 服务开启之后客户端可以用 HTTP 协议拉文件速度快得多而且支持多客户端并发。开启方式通常就是在界面上勾一个启用 HTTP的选项端口默认 80如果和机器上已有的服务冲突就改成 8080 之类。真正用起来的关键不在服务端而在引导脚本。iPXE 支持 http:// 开头的地址脚本里写成kernel http://192.168.10.1/boot/wimboot就会走 HTTP。PXELINUX 则不支持 HTTP新版本有 lpxelinux.0 可以但兼容性一般所以如果你用 PXELINUX大镜像还是得想办法通常是挂一个 SMB 或者 NFS 共享让 WinPE 启动之后自己去挂载。我的实际组合是TFTP 只负责发一个几百 KB 的 iPXE后面所有东西——wimboot、boot.sdi、boot.wim、ISO——全部走 HTTP。这样 TFTP 的压力几乎为零几十台机器同时开机也不会卡。3.4 config.ini 的手改法与容易改坏的地方界面上能配的东西有限很多细节要改 ini。改之前先备份一份这是我踩过坑之后的习惯。ini 的字段名一般能自解释但有几个地方的坑比较集中。一是路径分隔符。Windows 下习惯用反斜杠但 ini 里的路径有时需要转义或者干脆用正斜杠更保险。我改成全用正斜杠之后路径相关的报错基本绝迹了。二是布尔值的写法。有的版本用 1 和 0有的版本用 true 和 false混着写会解析失败。改的时候看一眼原文件里已有的写法照着来。三是行尾的注释和空格。有些解析器对行尾空格敏感删掉注释后留下的空格可能导致值多出一个字符。改完保存之前习惯性看一眼行尾。四是编码。用记事本保存成带 BOM 的 UTF-8某些版本会读不出来。用支持无 BOM 的编辑器保存比较省事。改完 ini 之后程序要重启才能生效。我一般会先在一台机器上试确认配置改动没问题再放开给全部机器。4. 引导文件怎么备从 PXELINUX 到 iPXE 再到 wimboot4.1 Legacy 路线pxelinux.0 加 ldlinux.c32 再加菜单文件PXELINUX 是 Syslinux 项目的一部分在 Legacy BIOS 环境下用得最广。它的核心文件是 pxelinux.0但只有这一个文件是跑不起来的还需要 ldlinux.c32 这个核心模块以及如果你想要一个可选择的菜单还得有 menu.c32 和字体文件。这几个文件之间是版本绑定的。pxelinux.0 是 6.03 版本ldlinux.c32 是 6.04 版本放在一起就可能报找不到模块或者直接黑屏。我第一次做的时候就是从不同的压缩包里各拿了一个卡了整整一个下午。后来学乖了永远从同一个版本的发行包整套提取。菜单文件放在 TFTP 根目录下的 pxelinux.cfg 文件夹里文件名一般是 default。这个文件里写每个启动项的 label、kernel、append 参数。比如一个典型的 Windows PE 启动项kernel 指向 wimbootappend 里用initrd依次挂上 bootmgr.exe、BCD、boot.sdi、boot.wim。顺序不能乱wimboot 对顺序有要求。PXELINUX 的优点是成熟、资料多、老机器兼容性好。缺点是它对 HTTP 支持有限而且菜单文件那一套语法比较古板写错一个字符就整个菜单不显示。4.2 UEFI 路线bootx64.efi 与 iPXE 之间的取舍UEFI 环境下引导文件名一般填 bootx64.efi这是 UEFI 规范里约定的默认引导程序名。但光有一个 bootx64.efi 还不够它通常是 GRUB2、iPXE 或者 Syslinux 的 UEFI 版本之一不同的实现后续的配置方式完全不同。我选的是 iPXE 的 UEFI 版本文件名叫 ipxe.efi 或者 snponly.efi。选它的原因是 iPXE 有脚本能力可以在脚本里判断网卡、拼 URL、走 HTTP比 GRUB2 的配置文件灵活得多。写一个简单的 ipxe 脚本几行就能实现显示菜单、默认十秒后自动进入、选中后从 HTTP 拉 wimboot 和 boot.wim。要注意的是 UEFI 有一个 Secure Boot 的机制。如果目标机器的 Secure Boot 是开启的未经签名的 iPXE 可能被固件拒绝加载表现就是加载到一半提示校验失败或者干脆重启。解决办法有两个一是在 BIOS 里把 Secure Boot 关掉这在自建机房里通常可以接受二是用签过名的引导程序但那就得走微软的签名流程成本很高。批量装机的话进 BIOS 关掉 Secure Boot 是最省事的做法虽然要多一道人工操作。还有一点某些主板的 UEFI 网络栈实现有问题加载 .efi 引导程序后会丢失网络连接导致后续 HTTP 拉文件失败。这种情况可以试试用 snponly.efi它直接使用网卡的 UEFI 驱动绕开固件自带的网络栈。4.3 WinPE 引导的关键几件套wimboot、boot.sdi、boot.wim要装 Windows中间必须经过 WinPE 这一层。WinPE 是一个精简的 Windows 环境它负责分区、展开镜像、写引导记录。把 WinPE 通过网络引导起来靠的是 iPXE 的 wimboot 模块。wimboot 本身是一个很小的二进制文件它的作用是解析 WIM 格式的镜像并把它当作启动镜像加载。要用它需要准备四样东西wimboot、bootmgr.exe、BCD、boot.sdi再加上实际的 boot.wim。前四个从 Windows 安装镜像的 sources 目录和 boot 目录里能找到boot.wim 也在 sources 目录下。iPXE 脚本里典型写法是这样的kernel http://192.168.10.1/boot/wimboot initrd http://192.168.10.1/boot/bootmgr.exe bootmgr.exe initrd http://192.168.10.1/boot/BCD BCD initrd http://192.168.10.1/boot/boot.sdi boot.sdi initrd http://192.168.10.1/boot/boot.wim boot.wim boot这里的顺序是 wimboot 要求的固定顺序改成别的顺序会加载失败。另外 BCD 这个文件是二进制的引导配置数据库它规定了 WinPE 启动时去哪个路径找系统。如果 BCD 里的路径和实际不符WinPE 会报错退出。boot.wim 有两个索引索引 1 是 Windows 安装程序索引 2 是 WinPE 本身。网络引导时要指定用哪一个通常用索引 2 更干净启动后直接进命令提示符或者自定义的启动脚本。索引 1 会直接进入安装界面如果想要全自动安装也可以用它。4.4 网卡驱动注入让新主板不至于卡在找不到网卡用 WinPE 网络引导有一个致命前提WinPE 自己得能联网或者至少能读到你放在网上的镜像。如果目标机器的网卡型号比较新而 boot.wim 里自带的驱动包不包含它结果就是 WinPE 起来了但找不到网卡后续所有需要网络的动作全部失败。这个问题的表现是图形界面卡在正在寻找网络或者命令提示符里 ipconfig 什么都没有。很多人会以为是 PXE 配置的问题其实是驱动的问题。解决办法是用 DISM 往 boot.wim 里注入驱动。先把 boot.wim 挂载到一个临时目录把网卡驱动的 inf、sys、cat 文件拷进去用 Add-Driver 命令注入然后卸载并提交。整套命令大概长这样dism /Mount-Image /ImageFile:boot.wim /Index:2 /MountDir:C:\mount dism /Image:C:\mount /Add-Driver /Driver:C:\drivers /Recurse dism /Unmount-Image /MountDir:C:\mount /Commit注入完的 boot.wim 体积会变大这是正常的。我一般会准备一个驱动库目录把近两年常见的主板网卡驱动都塞进去一次注入后面换机器就不用反复折腾。需要注意的是WinPE 的驱动模型和完整 Windows 不完全一样有些驱动在完整系统里能用在 WinPE 里加载会失败。注入之后一定要实际跑一遍确认网卡能识别、能拿到地址再批量开工。5. 让批量两个字落地无人值守与镜像分发5.1 Windowsautounattend.xml 里必须写对的几个节点引导起来只是第一步如果每台机器都要人工点下一步那批量装机就名不副实了。真正的自动化靠的是应答文件Windows 下叫 autounattend.xml。这个文件可以放在几个位置U 盘根目录、安装镜像根目录、或者通过 WinPE 启动参数指向一个网络地址。网络装机场景下我倾向放在 HTTP 根目录然后在 WinPE 的启动命令行里加上setup.exe /unattend:\\192.168.10.1\unattend\autounattend.xml这样的参数或者更简单直接把文件塞进 boot.wim 或者安装源目录里。应答文件里比较关键的几个节点磁盘分区配置、产品密钥、语言和时区、计算机名规则、管理员账户、以及首次登录后要执行的命令。磁盘分区配置最容易出问题因为不同机器的磁盘数量和容量不一样如果写死了磁盘号和分区大小遇到配置不同的机器就会报错。稳妥的做法是用 DiskConfiguration 里的 WillWipeDisk 和 ModifyPartitions 配合通配符或者干脆让安装程序自动分区。计算机名可以设成一个前缀加随机数或者序列号后几位避免几十台机器重名导致网络冲突。首次登录后执行的命令是挂后置脚本的入口我一般让它去拉一个批处理批处理里做装驱动、改注册表、装常用软件这些事。有一点要提醒autounattend.xml 里的密码是明文即便用 Base64 编码也只是编码不是加密。放在网络共享上要确保只有装机网段能访问装完之后及时删掉。5.2 Linuxkickstart 与 preseed 该怎么选要装 Linux 的话无人值守是另一套机制。RedHat 系用 kickstartks.cfgDebian 系用 preseed。两者都是把安装过程中的所有交互项提前写好安装程序启动时读这个文件一路自动走完。kickstart 文件通过内核启动参数指定比如在 PXELINUX 或者 iPXE 的菜单项里写append initrdinitrd.img kshttp://192.168.10.1/ks/centos.ks。文件内容大致分几块安装源地址、磁盘分区方案、网络配置、软件包选择、安装后脚本。安装后脚本是做批量定制的关键可以在这里统一改主机名、配 yum 源、装监控 agent。需要留神的是安装源。如果没把完整的安装镜像挂到 HTTP 上kickstart 会去找默认的源地址在国内网络环境下大概率超时。老老实实把 ISO 解开放在 HTTP 根目录然后 ks 里用url --urlhttp://192.168.10.1/os/指定本地源最不容易出岔子。preseed 的思路类似只是参数名和文件格式不一样而且它是通过内核参数autotrue prioritycritical urlhttp://...指定。两种机制我都用过kickstart 的文档和示例更多遇到问题更好查。5.3 镜像瘦身与传输提速的几个实操手段几十台机器同时从一台服务器拉镜像带宽和磁盘 IO 都会成为瓶颈。我做过一次测算一个 5 GB 的 install.wim 分发给三十台机器如果服务器网卡是千兆理论上限是 125 MB/s全部传完至少要二十分钟而且这期间服务器什么别的都干不了。几个提速的做法值得一试。把镜像格式从 wim 转成 esd 或者用压缩率更高的方式打包体积能减少三到四成代价是解压时 CPU 占用高一点但因为传输时间大幅缩短整体还是赚。把镜像放在 SSD 上避免机械盘成为瓶颈。网卡如果支持链路聚合把两条千兆绑在一起带宽直接翻倍。还有一个思路是分批上线。不要三十台一起开机而是分三批每批十台这样单台的下载速度能维持在比较理想的水平整体耗时反而更短。PXE 服务端还有个细节TFTP 是 UDP 单线程的几十个客户端同时请求小文件很容易丢包重传所以把引导文件做得越小越好让 TFTP 阶段快速过去把大头都交给 HTTP。6. 故障排查从 PXE-E32 到 No boot filename received6.1 一套固定的排查顺序照着走就行排查 PXE 问题最怕东一榔头西一棒子我今天查 DHCP明天查 TFTP最后发现问题在网线。我总结了一套固定顺序按链路从下往上走基本能在十分钟内定位。第一步看物理层。网线插好没有、交换机端口灯亮不亮、网卡在 BIOS 里有没有启用网络引导。这一步能解决大概两成的问题尤其是新机房里线序做错、跳线坏掉这类事。第二步看客户端拿没拿到地址。如果 PXE 阶段连正在获取 IP都过不去那就是 DHCP 层面的问题检查服务有没有启动、地址池有没有配错、绑定的是不是正确的网卡、有没有和别的 DHCP 服务器打架。第三步看引导文件名。拿到地址之后客户端会请求引导文件这一步失败通常提示没有收到启动文件名或者TFTP 打开超时。先去 TFTP 根目录确认文件名存在再确认大小写和路径分隔符最后确认防火墙放行了对应端口。第四步看引导程序跑没跑起来。引导程序加载成功后会出菜单或者出 iPXE 的命令行界面。如果到这里黑屏或者重启多半是引导文件版本不匹配或者固件环境不对。第五步看大文件传输。菜单出来之后加载镜像卡住问题在 HTTP 服务或者镜像本身。用浏览器直接访问那个 URL 试试能下载说明服务没问题那就是引导脚本里的地址写错了。6.2 常见报错对照表报错信息可能的根因处理动作PXE-E51: No DHCP or proxyDHCP offers were received服务未启动、地址池耗尽、绑定网卡错误检查服务状态与网卡绑定核对地址池范围PXE-E53: No boot filename received启动文件名未配置或配置为空在 DHCP 面板填写正确的引导文件名PXE-E32: TFTP open timeoutTFTP 服务未启动、防火墙拦截、文件名不存在放行 UDP 69 端口确认文件在 TFTP 根目录PXE-E55: ProxyDHCP service did not reply客户端广播被拦截、服务端不在同一广播域检查交换机配置与 VLAN 划分引导菜单显示但加载镜像失败HTTP 地址错误、镜像文件缺失、路径大小写不符用浏览器直接访问 URL 验证UEFI 下提示 boot failed引导文件不是 efi 版本、Secure Boot 开启换用 efi 引导文件关闭 Secure BootWinPE 启动后找不到网卡boot.wim 缺少对应驱动用 DISM 注入网卡驱动后重新生成这张表是我自己遇到过的报错汇总大部分场景都能在里面找到对应项。表里没有的情况就得靠抓包了。6.3 抓包这件事什么时候值得做前面五步都排完了还是找不到原因就该抓包了。在服务端机器上开着抓包工具过滤 UDP 67 和 68 端口重启一台客户端看整个交互过程。正常的流程是客户端广播 DHCPDISCOVER服务端回 DHCPOFFER客户端发 DHCPREQUEST服务端回 DHCPACK紧接着客户端向 TFTP 端口 69 发请求。如果中间某一步断了问题就锁定在那一环。抓包能看出很多表面看不出的东西。比如服务端确实回了 DHCPOFFER但里面有启动文件名这一项是空的那问题就在配置而不是网络。又比如客户端发了多次 DHCPREQUEST 但服务端一次没回说明请求根本没到达服务端中间有设备在拦截。这个手段听起来重但真遇到疑难问题时是最快的。我遇到过一次偶发失败的情况十台机器里有两台死活进不去 PXE抓包一看这两台的 DHCP 请求延迟比其他机器高出几百毫秒原因是它们接在一个串联的下级交换机上中间多了一跳。把线改接主交换机之后问题消失。7. 规模化装机之后的几点运维心得7.1 并发上线时的瓶颈在哪一次装十台和一次装五十台瓶颈位置完全不同。十台的时候基本感觉不到压力五十台一起上的话最先扛不住的往往是 TFTP。它是 UDP 服务没有连接状态每个包都要单独确认几十个客户端同时请求几百 KB 的引导文件时丢包率会明显上升。我的应对是把引导层压缩到极致。能用一个引导文件解决就绝不用两个能在脚本里少写一行就少写一行。iPXE 的好处就是它可以把大部分逻辑放在脚本里引导文件本身只有几百 KB。另外把 TFTP 的超时时间和重传次数适当调大一点给网络留点余量。第二个瓶颈是服务器磁盘。镜像文件放在机械盘上几十个 HTTP 请求同时打过来磁头来回寻道速度会掉到几 MB/s。换 SSD 之后这个问题基本消失如果条件允许把镜像提前读进系统缓存效果更好。第三个瓶颈其实是交换机。很多便宜的千兆交换机背板带宽不足多个端口同时大流量传输的时候实际每端口速率会掉。这个不太好从软件层面解决只能分批上线或者换设备。7.2 镜像仓库的版本管理与回滚装了几轮之后你会发现镜像不是一成不变的。今天加个新驱动明天改个配置后天换个软件版本。如果每次都直接在原镜像上改出了问题是回不去的。我的做法是给每个镜像建立一个版本目录比如 v1、v2、v3引导脚本里用一个变量指向当前生效的版本。发现新版本有问题改一个变量就能退回旧版本不用重新打包。目录里同时放一个说明文件记清楚这一版改了什么、什么时候改的、谁改的。镜像文件本身也要留一份基准。我用的是最原始的 Windows 安装镜像加一版已经定制好的镜像并存出问题的时候能快速判断是定制环节的问题还是原始镜像的问题。还有一点装完机器的机器上跑的系统和你手上的镜像可能会慢慢偏离因为用户会改设置、装软件。定期从一台标准机器上重新采集镜像能避免版本漂移得太远。7.3 装完之后别忘了收尾装机这件事装完不等于结束。还有几件事必须做否则后面会惹麻烦。第一是关掉服务。装完之后把 DHCP 和 TFTP 服务停掉尤其是 DHCP如果留着它会和正常使用的 DHCP 服务器抢地址表现就是随机断网。我在一个项目上忘了这回事一周后接到电话说整个部门网络时断时续查了半天才发现是自己留下的 DHCP 在捣乱。第二是清理应答文件里的密码和密钥。autounattend.xml 和 ks.cfg 里往往带着管理员密码这些文件在装完之后就没用了留在共享目录里是个隐患。第三是记录。记清楚这次用了哪个版本的镜像、哪套引导文件、地址池范围下次再装同样的机器时可以直接复用。我把这些信息写成一个简短的文档放在镜像目录里省得下次再从零回忆。我在实际操作中的体会是PXE 批量装机这件事的价值不在于工具本身有多强而在于你愿不愿意花两三个小时把前面那几步做扎实。网络想清楚了、引导文件备对了、应答文件写全了剩下的事情就是按电源键和等几十台机器一个下午全刷完那种感觉比你插五十次 U 盘要舒服太多。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。