机房手记

  • 首页
  • 服务器硬件
  • Linux 运维
  • GPU 服务器
  • 站内搜索
服务器硬件与运维实战
RAID 阵列 · 内存与固件 · GPU 服务器 —— 一线工程师的故障实录
  1. 首页
  2. GPU服务器
  3. 正文

用 Redfish API 批量初始化服务器 BMC:交付流程全脚本化

2026年10月22日 68点热度 0人点赞 0条评论

服务器上架交付时,最耗时间的往往不是插线缆,而是初始化:核对固件版本、调整 BIOS 参数、设置 PXE 启动顺序、装完系统再翻一遍 SEL 日志确认没有硬件告警。这些操作全都发生在 BMC 网页里——点一下是几十秒的事,批量做就是灾难。

更麻烦的不是慢,是不一致。手工点击时人是会走神的:改到第 3 台忘了翻某个下拉框,第 6 台误以为上一台已经改过。整批跑完,你拿不出任何东西证明它们的参数完全一致。

本文记录如何用 Redfish API 把这套流程全面脚本化,涵盖资源树定位、主机与 BMC 的内网通路、五类交付动作的 curl 实现、etag 与翻页处理,以及一份踩坑清单。

适用机型:DGX H 系列(BMC 与 SBIOS 出厂即启用 Redfish)
覆盖范围:资源树定位、内网通路、五类交付动作的 curl 实现、etag 与翻页处理、踩坑清单


一、Redfish 凭什么能替掉网页

IPMI 已经是带外管理的事实标准,但交付阶段真正要动的那些东西——BIOS 参数、启动顺序、固件版本——它一个都碰不到。Redfish 是 DMTF 定义的标准,走 HTTPS + JSON,覆盖范围是 IPMI 的超集。

维度 IPMI / ipmitool Redfish
协议 RMCP+ 二进制 HTTPS + JSON
能干的活 电源、传感器、SEL、账号 上述全部,外加 BIOS 设置、启动顺序、固件更新、虚拟媒体、配置备份、遥测、功率封顶
输出可读性 命令行参数,得记 JSON,看一眼就懂
自动化 可以,但每个厂商参数不一致 标准端点,curl 直接调

关键差别就一行:交付要动的 BIOS、启动顺序、固件,只有 Redfish 能碰。

而且端点是标准的——所有请求都从 https://<bmc-ip>/redfish/v1 往下找。想知道"改启动顺序该打哪个地址",看一眼资源树就行。

主机与 BMC 之间的内部通路

交付场景里有一条非常实用的东西:主机和 BMC 之间有一条内部网络通路。你可以在主机上配一个 169.254.0.0/16 网段的接口(BMC 侧预置 169.254.0.17),脚本既不用绕管理网,也不用把 BMC 暴露在业务网里:

sudo ifconfig <主机侧网卡> 169.254.0.18 netmask 255.255.0.0

配完之后,curl、nvfwupd 直接打 169.254.0.17 就行:

nvfwupd -t ip=169.254.0.17 username=<bmc-user> password=<password> show_version

二、资源树:一个入口,五棵子树

所有请求都从 /redfish/v1 往下找。按用途分成五棵子树:

DGX 的 Redfish 资源树:一个入口,五棵子树
  • /redfish/v1/Managers/BMC —— 账号、重置、SEL 日志、虚拟媒体、备份
  • /redfish/v1/Systems/DGX —— SBIOS 设置、启动顺序、Secure Boot、电源
  • /redfish/v1/Chassis/DGX —— 传感器:温度、功率、风扇
  • /redfish/v1/UpdateService —— 固件清单、上传、激活、强制更新
  • /redfish/v1/TelemetryService —— GPU 托盘指标、功率封顶(NodeManager)

想干什么,先定位到哪棵子树,路径就确定了。

三、交付要做的五件事,逐个 curl 化

下面的命令里,<bmc-user>、<password>、<bmc-ip> 三个占位符按现场替换。-k 是跳过证书校验——BMC 用的是自签证书,不加会直接失败。

DGX 交付时的带外批量初始化流程:五步全部可脚本化

第一步:核固件清单

交付第一步是核固件,不是刷固件。机型 SOP 上写死了各组件应该是什么版本,先对表,对不上的才动手。一上来就刷,刷错版本反而添乱。

curl -k -u <bmc-user>:<password> --request GET 
  'https://<bmc-ip>/redfish/v1/UpdateService/FirmwareInventory'

返回的是一个集合,DGX H 系列上一眼能看到 Members@odata.count 是 66 上下。每一项是 CPLDMB_0、HostBMC_0、PSU_0 这类组件名,版本号在 Oem.Ami.FirmwareInventory 里成对给出。

需要升级时,按组件分两类目标:

要更新的部分 target 怎么写 固件包
GPU 托盘(整套 GPU 托盘组件) HGX_0 nvfw_HGX_DGXH100-H200x8_xxxxxx.x.x.fwpkg
主板托盘(BMC / BIOS / CPLD / PSU / PCIe Switch 等) HostBMC_0、HostBIOS_0、CPLDMB_0 等 nvfw_DGX_xxxxxx.x.x.fwpkg

上传和刷写:

echo '{"Targets":["/redfish/v1/UpdateService/FirmwareInventory/HostBMC_0"]}' > parameters.json

curl -k -u <bmc-user>:<password> -H 'Expect:' --location --request POST 
  https://<bmc-ip>/redfish/v1/UpdateService/upload 
  -F 'UpdateParameters=@parameters.json;type=application/json' 
  -F UpdateFile=@<fw_bundle>

那个 -H 'Expect:' 不是可有可无的。不加的时候 curl 会先发一个 Expect: 100-continue 探路,部分 BMC 固件对这个处理得不好,表现是卡住不动、也不报错。

另外固件默认只升不降(版本必须高于当前值才写)。要强行覆盖,先改这个开关:

curl -k -u <bmc-user>:<password> --request PATCH 
  'https://<bmc-ip>/redfish/v1/UpdateService' 
  --header 'If-Match: *' 
  --header 'Content-Type: application/json' 
  --data-raw '{"HttpPushUriOptions" : {"ForceUpdate": true}}'

改动成功返回 204;如果你设的值和当前值一样,会返回 400。以前核固件要一台台登进去对,现在一条 curl 把 66 个组件的版本全拉下来。

第二步:改 BIOS 设置

BIOS 参数不是想改就能改。属性名写错一个字母,BMC 不一定报错,可能就静静忽略了。所以第一步不是改,是先把这台机器支持的属性清单拉下来。三跳:

# 1) 列出所有注册表,找到 BIOS 属性注册表
curl -k -u <bmc-user>:<password> --location --request GET 
  'https://<bmc-ip>/redfish/v1/Registries'

# 2) 拿注册表 URI(名字形如 BiosAttributeRegistry106.1.0.6)
curl -k -u <bmc-user>:<password> --location --request GET 
  'https://<bmc-ip>/redfish/v1/Registries/BiosAttributeRegistry106.1.0.6/'

# 3) 把属性定义 JSON 拉下来
curl -k -u <bmc-user>:<password> --location --request GET 
  'https://<bmc-ip>/redfish/v1/Registries/BiosAttributeRegistry106.en-US.1.0.6.json' 
  --output BiosAttributeRegistry106.en-US.1.0.6.json

这份 JSON 是属性字典:每个属性名对应默认值、显示名、帮助文本、是否只读、是否需要重启才生效。改参数前先在这儿确认属性名拼写,写错了 BMC 不一定报错,可能就静静忽略了。

看当前生效值:

curl -k -u <bmc-user>:<password> --location --request GET 
  'https://<bmc-ip>/redfish/v1/Systems/DGX/Bios'

写"下次启动生效"的值,PATCH 到 Bios/SD:

curl -k -u <bmc-user>:<password> --location --request PATCH 
  'https://<bmc-ip>/redfish/v1/Systems/DGX/Bios/SD' 
  -H 'Content-Type: application/json' -H 'If-Match:*' 
  --data-raw '{"Attributes" : {"IPMI002":"IPMI002DoNothing", "IPMI201":"IPMI201Donotloganymore"}}'

上面这两个属性是 SEL 日志满的时候系统怎么办。IPMI002 是写满之后的动作,IPMI201 是满了还继续记录与否。交付时按客户要求选,不选的话默认行为可能是停止记录,之后出问题就没日志可查了。一次 PATCH 可以带多个属性。

⚠️ BIOS 属性的改动,全部需要一次断电再上电(power cycle)才生效。而且如果你改完属性紧接着又刷了 BIOS 固件,还得再来一次 power cycle。判断是否落地的方法很简单:Bios 端点返回当前值,Bios/SD 返回"下次启动生效"的值,两个对不上就说明还没落地。

第三步:改启动顺序

启动顺序不对,PXE 装机流程接不上,机器就躺在机柜里等。这一步必做,也最容易写错,因为它要先读再写。

先读当前顺序:

curl -k -u <bmc-user>:<password> 
  https://<bmc-ip>/redfish/v1/Systems/DGX/SD 
  -H "content-type:application/json" -X GET -s | jq .Boot.BootOrder

拿到一串 Boot0000、Boot000F 这样的编号。光看编号不知道谁是谁,得再查一遍:

curl -k -u <bmc-user>:<password> 
  https://<bmc-ip>/redfish/v1/Systems/DGX/BootOptions/00{0,1}{0,4,5,6,7,8,9,A,F} 
  -H "content-type:application/json" -X GET -s | jq | grep -e "UefiDevicePath|Name"

这里用了个 shell 的大括号展开,一次把 Boot0000、Boot0001、Boot0004 一直到 Boot0010 全查了,不用写循环。

返回里三个字段有用:

  • DisplayName —— 设备的可读名字,比如 UEFI: PXE IPv4 Nvidia Network Adapter - 00:AA:BB:00:00:01、DGX OS
  • Name —— 对应的启动项编号
  • UefiDevicePath 里的 MAC(<地址>,0x1) —— 这块网口的 MAC。多个口名字长得一样的时候,靠这个区分

确认好顺序之后写回去:

curl -k -u <bmc-user>:<password> 
  https://<bmc-ip>/redfish/v1/Systems/DGX/SD 
  -H "content-type:application/json" 
  -H 'If-Match: "<etag>"' 
  --data '{"Boot":{"BootOrder": ["Boot0004","Boot0000","Boot0005","Boot0006","Boot0007","Boot0008","Boot0009","Boot000A","Boot000F","Boot0010"]}}' 
  -X PATCH

数组是全量覆盖,不是增量。没写进数组的启动项不会自动保留在末尾。正确做法是:把读回来的完整列表拿出来,只把要提前的那一项挪到最前面,其余原样跟上去。

写完再读一遍确认:

curl -k -u <bmc-user>:<password> 
  https://<bmc-ip>/redfish/v1/Systems/DGX/SD 
  -H "content-type:application/json" -X GET -s | jq .Boot.BootOrder

这个顺序会一直保留到下次被改写,或者 SBIOS 被重置。以前要登网页翻菜单,现在读出来、改、写回去,一套动作三行命令。

第四步:电源循环

改完 BIOS、改完启动顺序,别急着看结果——那些值都还只是"下次启动生效",没断电重上电,根本不落地。你进系统一看还是老样子,会怀疑自己白改了半天。

Redfish 的电源操作全在同一组端点上,差别只在 ResetType:

想要的效果 ResetType
开机 On
直接断电 ForceOff
软关机 GracefulShutdown
直接重启 ForceRestart
软重启 GracefulRestart
断电再上电 PowerCycle
curl -k -u <bmc-user>:<password> --request POST 
  --location 'https://<bmc-ip>/redfish/v1/Systems/DGX/Actions/ComputerSystem.Reset' 
  --header 'Content-Type: application/json' 
  --data '{ "ResetType": "PowerCycle" }'

⚠️ 交付场景里要的是 PowerCycle 不是 ForceRestart。改 BIOS 参数这类操作,重启(restart)不算数,要的是断电再上电——有些参数只在完整的上电初始化流程里才被读进去。

另外注意:管理板(HMC)上不支持 ForceRestart、GracefulRestart、GracefulShutdown 这三种,别拿同一套脚本无脑刷。

第五步:收口核查

前面四步都在写,最后一步得扫一遍,确认没写坏什么。机器交付出去才发现 SEL 里躺着一条 DIMM 告警,那才叫丢人。

curl -k -u <bmc-user>:<password> --location --request GET 
  'https://<bmc-ip>/redfish/v1/Managers/BMC/LogServices/SEL/Entries'

curl -k -u <bmc-user>:<password> --location --request GET 
  'https://<bmc-ip>/redfish/v1/Chassis/DGX/Sensors'

这两个端点都要翻页,而且不会提醒你。SEL 和 Chassis/DGX/Sensors 每次都只返回 75 个成员,剩下的靠 Members@odata.nextLink 给地址。只看一页就以为"日志挺干净",后面可能还藏着一条 DIMM 告警。

翻页就是顺着 nextLink 里的 $skip 往下走:

curl -k -u <bmc-user>:<password> --request GET 
  'https://<bmc-ip>/redfish/v1/Managers/BMC/LogServices/SEL/Entries?$skip=75'

判断依据是返回值里有没有 nextLink:有就继续拉。

批量交付的时候,这几步串起来就是一个循环:读清单文件里的 BMC IP,对每台依次跑上面五步,把每台的返回按 IP 存成独立文件。哪台失败、失败在哪一步,都在文件名和日志里。

四、六个踩过的坑

1. 第一次上手,资源树从哪进都不知道。所有请求都从 https://<bmc-ip>/redfish/v1 往下找,但机型路径里的 DGX 是固定的,不是变量——写成 Systems/1 之类会直接 404。

2. 改完 BIOS 不 power cycle,等于没改。改完就重启,进系统一看参数没变,会误以为是权限问题。判断标准:Bios 返回当前值,Bios/SD 返回"下次启动生效"的值,两个对不上就是没落地。

3. -H 'Expect:' 刷固件时必须加。不加就卡住,而且不报错。这类"静默失败"比报错难查得多——curl 那个 Expect: 100-continue 探路会把部分 BMC 卡住。

4. SEL 和 Sensors 会静默截断。75 条一页,不翻页就以为看全了。判断依据是返回值里有没有 nextLink。

5. 写操作尽量带 etag。etag 对不上会返回 412。这不是麻烦,是保护——防止两个进程同时改同一台。注意不同固件文档写法可能不同(有的写成 if-None-Match),以实际返回为准。

6. 别把写操作并发化。BMC 只有一颗,多个 PATCH 同时打过去,轻则返回 500,重则把 BMC 搞到要重启。正确做法是读可以并发、写串行,一台改完确认了再下一台。

五、这套东西省了哪些事

  • 参数可对账:每台机器的固件版本、BIOS 当前值、启动顺序都能拉成文本,交付记录里附一份,比"我点过了"有说服力
  • 一致性有保障:同一段脚本跑 8 次,参数不会因为人飘而漂移
  • 不用登网页:机器还在机柜走线阶段就能操作,只要 BMC 通了电和网
  • 可回滚:配置文件写前先 GET 存档,改坏了能按原值写回
  • 能接进交付流水线:跟 PXE 装机、配置下发串成一个脚本,一条命令批量下发

六、批量脚本的骨架

把上面的流程串成一个可复用的脚本,大致是这个结构:

#!/usr/bin/env bash
# 批量 BMC 初始化:读 - 写 - 读回校验,三步走
set -euo pipefail

BMC_LIST="bmc-list.txt"        # 每行一个 BMC IP
USER="<bmc-user>"
PASS="<password>"

rf() {   # 统一封装 curl,简化后续调用
  local ip="$1"; shift
  curl -k -sS -u "${USER}:${PASS}" "$@"
}

while read -r ip; do
  [ -z "$ip" ] && continue
  echo "=== 处理 ${ip} ==="

  # 1) 归档当前配置(回滚用)
  rf "$ip" "https://${ip}/redfish/v1/Systems/DGX/Bios" 
    -o "backup/${ip}-bios.json"
  rf "$ip" "https://${ip}/redfish/v1/Systems/DGX/SD" 
    -o "backup/${ip}-boot.json"

  # 2) 下发 BIOS 设置(写操作串行)
  rf "$ip" "https://${ip}/redfish/v1/Systems/DGX/Bios/SD" 
    -X PATCH -H 'Content-Type: application/json' -H 'If-Match:*' 
    --data-raw '{"Attributes":{"IPMI002":"IPMI002DoNothing","IPMI201":"IPMI201Donotloganymore"}}'

  # 3) 读回 BootOrder,改好再写
  order=$(rf "$ip" "https://${ip}/redfish/v1/Systems/DGX/SD" | jq -c '.Boot.BootOrder')
  new=$(echo "$order" | jq -c '["Boot0004"] + (. - ["Boot0004"])')
  rf "$ip" "https://${ip}/redfish/v1/Systems/DGX/SD" 
    -X PATCH -H 'Content-Type: application/json' 
    --data "{"Boot":{"BootOrder":${new}}}"

  # 4) power cycle,让改动落地
  rf "$ip" "https://${ip}/redfish/v1/Systems/DGX/Actions/ComputerSystem.Reset" 
    -X POST -H 'Content-Type: application/json' 
    --data '{"ResetType":"PowerCycle"}'

  # 5) 收口核查(含翻页)
  skip=0
  while :; do
    page=$(rf "$ip" "https://${ip}/redfish/v1/Managers/BMC/LogServices/SEL/Entries?$skip=${skip}")
    echo "$page" | jq -c '.Members[]' >> "log/${ip}-sel.jsonl"
    next=$(echo "$page" | jq -r '.Members@odata.nextLink // empty')
    [ -z "$next" ] && break
    skip=$((skip + 75))
  done

done < "$BMC_LIST"

⚠️ 执行前务必确认:

  • 目标 BMC IP 列表准确——脚本会真的改配置并断电重启
  • BIOS 属性名在目标机型上真实存在(先拉注册表核对)
  • 每台操作前已归档 Bios 与 SD,便于回滚
  • 避开业务高峰期,power cycle 会中断正在运行的服务

结语

带外管理的价值不在于"能远程开机",而在于把一批机器配置成完全一致的状态,并且能拿出证据证明它们确实一致。手工点击在这两点上都是做不到的——人一定会飘。

Redfish 的门槛其实不高:记住 /redfish/v1 是唯一入口,剩下的顺着资源树找就行。真要上手,建议先拿一台机器把五步各跑一遍,把 curl 输出存下来对照,然后再改写成循环。


本文技术方法与命令为笔者整理并实测验证。案例原型参考自技术社区公开文章《一台台登 BMC 改配置,我改用 Redfish API 批量下发》(公众号「闫工的算力工具箱」),在此致谢并推荐阅读原文:https://mp.weixin.qq.com/s/1LodZCcde80ABg-kOEzyhA。本文为原创整理与扩展,转载请注明出处。文中示意图版权归原作者所有。

标签: 暂无
最后更新:2026年10月22日

机房手记编辑部

这个人很懒,什么都没留下

点赞
< 上一篇

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复
目录Toggle Table of ContentToggle
  • 一、Redfish 凭什么能替掉网页
    • 主机与 BMC 之间的内部通路
  • 二、资源树:一个入口,五棵子树
  • 三、交付要做的五件事,逐个 curl 化
    • 第一步:核固件清单
    • 第二步:改 BIOS 设置
    • 第三步:改启动顺序
    • 第四步:电源循环
    • 第五步:收口核查
  • 四、六个踩过的坑
  • 五、这套东西省了哪些事
  • 六、批量脚本的骨架
  • 结语

© 2026 机房手记 · 运维手记本站内容,转载请注明出处

专注服务器硬件与 Linux 运维实战