网卡MAC硬刷不失效:NVM定位、ethtool写入与回滚避坑
简介:这份「MAC地址硬刷工具」是面向具备一定网络与硬件基础的用户整理的网卡物理地址修改工具合集,可用于群晖等系统环境下的网络标识调整、虚拟机 MAC 唯一性维护以及异常网卡识别修复,帮助读者在特定网络配置场景中完成 MAC 地址改写与验证。压缩包共 197 个文件,约 4.52MB,包含 exe、bat 等刷写与批处理入口,cfg、ini 参数配置,docx、txt 操作说明,以及 bin、eep、c、h 等固件备份、芯片适配与源码资料,整体按工具和网卡类型分散组织。目前已有 2552 人学习下载。资源价值在于把操作文档、配置模板、批处理流程和多种网卡芯片适配资料集中在一起,便于读者对照现有硬件查找可用工具、理解刷写参数与风险点,并借助日志和备份文件完成排错与恢复参考。
1. 网卡 MAC 改不干净,多半是写错了层
上周帮某实验室收拾一批工控机,网络准入按 MAC 白名单放行。换了一批网卡之后,运维在系统里把 MAC 地址硬刷成台账上的值,ip link看是对的,一重启全变回原厂地址,几十台机器白名单集体失效。这不是玄学,是写错了层。MAC 实际存在三个位置:网卡 NVM/EEPROM 里的出厂值、驱动加载时读进内存的运行时值、系统或管理软件下发的覆盖值。后者随重启蒸发,前者才是设备真正的身份。所谓硬刷,指的是把新地址落到第一层,让任何系统、任何启动方式读出来都是它。这件事在资产标识规范化、测试环境地址冲突排查、虚拟机克隆后批量重号这些场景里是刚需;但如果你的目的是对抗某种按 MAC 计费的机制,那这条路本身就不该走,也不在本篇讨论范围内。真正难的不是敲哪条命令,而是判断手上这块卡能不能写、写到哪个偏移、写坏了怎么救。
2. 动手前先建档:PCI 地址、驱动、NVM 布局三样缺一不可
硬刷翻车的案例里,八成是在没搞清楚硬件型号的情况下直接照抄网上的命令。同一台机器上可能插着三块网卡,板载千兆、PCIe 万兆、USB 转接,它们的 NVM 结构和写入方式完全不同,USB 网卡甚至根本没有可写的 EEPROM,MAC 烧在芯片内部由固件模拟。所以第一步永远不是写,是读:把设备的身份信息、驱动、NVM 内容全部落到纸面上,后面所有参数都从这里推。
2.1 用 lspci 和 ethtool -i 锁定设备身份
先确认你要改的是哪块卡。多网口机器上eth0、eth1的编号会随内核版本和插槽顺序漂移,靠名字认卡迟早出事。正确做法是先拿 PCI 地址作为唯一锚点,再由 PCI 地址反查网口名。
# 1. 列出所有以太网控制器,记录 PCI 地址与厂商/设备 ID lspci -nn | grep -i ethernet # 2. 由 PCI 地址反查网口名(用上一步看到的地址,例如 0000:03:00.0) ls -l /sys/class/net/*/device | grep 0000:03:00.0 # 3. 读取驱动、固件版本、总线信息 ethtool -i eth0lspci -nn里的四位十六进制 ID,前一个是厂商 ID,后一个是设备 ID,这两个值决定了你后面能用哪家的烧写工具、ethtool -E支持的 magic 值大概在什么范围。ethtool -i输出的driver字段非常关键,它直接决定ethtool -E能不能用:只有驱动里实现了set_eeprom回调,这个命令才会真正下发写操作,否则报Cannot set EEPROM data。firmware-version也要记下来,部分卡固件版本过低时会锁定 NVM 写保护,必须先升级固件。
ls -l /sys/class/net/*/device那条命令的输出形如/sys/class/net/eth0 -> ../../devices/pci0000:00/0000:00:1c.0/0000:03:00.0/net/eth0,中间的 PCI 地址就是物理槽位。把「槽位 - 网口名 - 原厂 MAC - 驱动 - 固件版本」抄进一张表,这张表就是你后面回滚的唯一依据。
提示:机器有多块同型号网卡时,建议在 BIOS 里先把不打算改的网口禁用,或者直接拔掉数据线只留一块在链路里操作,避免命令打错网口。
2.2 用 ethtool -e 读出原始 NVM 并定位 MAC 偏移
ethtool -e是读 NVM 的标准入口,默认输出前 128 字节的十六进制转储。MAC 通常以连续 6 字节的形式存在某段固定偏移上,你要做的是把它找出来,并确认这段偏移在写入时不会被校验和区域覆盖。
# 读取默认长度(128 字节),人能看懂的十六进制格式 ethtool -e eth0 # 读更大范围,覆盖整个 NVM 前 512 字节 ethtool -e eth0 offset 0 length 512 # 直接导出为二进制文件做备份,这份文件是后面的后悔药 ethtool -e eth0 raw on offset 0 length 512 > eth0-nvm-backup.bin # 在转储里搜索当前 MAC 的字节序列(把冒号去掉,转成小写连续串) ethtool -e eth0 raw on offset 0 length 512 | xxd -p | tr -d '\n' | grep -bo "001122334455"输出形如Offset Values两列,左边是偏移,右边是 16 个字节。找到当前 MAC 出现的位置有两种方法:一是肉眼比对,二是上面第四条命令,grep -bo返回的是匹配位置在十六进制串里的字符下标,除以 2 就是字节偏移。注意网卡 EEPROM 里 MAC 有可能以反序存储(低字节在前),此时需要把 MAC 倒过来再搜一次,这是很多教程没提的细节,也是照抄命令后写错位置的头号原因。
备份文件一定要存两份,一份放本机/root/nvm-backup/,一份拷到外部存储。ethtool -E没有官方回滚命令,恢复全靠ethtool -E逐字节写回或者厂商工具导入 dump 文件,备份丢失基本等于报废一块卡。
2.3 可写性判断:四类网卡四种处理方式
读完 NVM,接下来要判断这块卡属于哪一类,处理方式差别很大:
| 网卡类型 | NVM 可写性 | 推荐做法 | 风险 |
|---|---|---|---|
| 板载千兆(PCIe 接口) | 一般可写,驱动多实现 set_eeprom | ethtool -E或厂商 DOS/EFI 工具 | 中,偏移算错会破坏校验区 |
| 独立 PCIe 万兆 | 可写,但多数需要厂商专用工具,ethtool -E常被驱动禁用 | 厂商 NVM 烧写工具 + 配置文件批量导入 | 中高,工具版本与固件版本强绑定 |
| USB 转以太网 | 不可写,MAC 由芯片内部固件模拟 | 改驱动层或系统层,放弃硬刷 | 低,但重启可能失效 |
| 虚拟网卡 | 无物理 NVM | 改虚拟机配置文件里的静态 MAC | 低,注意别和宿主机或其他虚机撞车 |
判断依据很直接:先试ethtool -E是否返回Cannot set EEPROM data或Operation not supported,再看/sys/class/net/eth0/device/下有没有eeprom相关属性。返回不支持就不要再折腾ethtool了,去翻厂商随驱动包提供的烧写工具,这类工具通常要求在纯 DOS 或 UEFI Shell 下运行,带自己的参数文件。
3. 三档改法落地:从 ip link 到 ethtool -E 的递进
改 MAC 有三档强度,代价和持久性依次上升。第一档只改运行时,重启即失效,适合临时排查地址冲突;第二档写进 NVM,换系统换启动方式都还在;第三档是 Windows 下通过驱动注册表间接下发,能不能持久取决于驱动实现。实际项目里我一般先跑第一档验证业务是否恢复正常,确认无误再上第二档,避免一上来就把卡写坏还得换硬件。
3.1 最轻的一档:ip link 与 macchanger 改运行时地址
这一档改的是内核里net_device结构体的dev_addr,不碰 NVM,掉电即还原。优点是零风险、秒生效,缺点是重启失效、部分管理软件(比如按 MAC 分配 IP 的 DHCP 服务端)会通过 ARP 探测识破。
# 先关接口,改地址,再启用;部分驱动不要求 down,但 down 之后成功率更高 ip link set dev eth0 down ip link set dev eth0 address 02:11:22:33:44:55 ip link set dev eth0 up # 立刻回读确认,注意看 link/ether 这一行 ip link show eth0 | grep link/ether # 如果装了 macchanger,可以顺手把永久地址和随机地址都看一眼 macchanger -s eth0 macchanger -m 02:11:22:33:44:55 eth0address后面跟的必须是 6 组两位十六进制,用冒号分隔。这里有个血泪经验:首字节不要随便取,02开头表示本地管理地址(第二低位为 1),这是手工分配的规范写法;如果你写成00或01开头,00开头可能撞上厂商 OUI 段,01开头则因为组播位(最低位)为 1 而被内核直接拒绝,报RTNETLINK answers: Invalid argument。
macchanger -m与ip link效果一样,都是运行时修改,区别是macchanger会自动帮你处理接口 up/down 和厂商前缀,代价是多装一个包。生产环境我倾向只用ip,少一个依赖少一个版本问题。
3.2 写入 NVM:ethtool -E 的 magic、offset、value 三个参数
这一档才是真正的硬刷。ethtool -E每次只能写一个字节,所以要写 6 次。三个参数必须全部正确:magic是驱动定义的魔数,用于防止误写,值随驱动不同而不同,需要查对应驱动源码里的ETHTOOL_EEPROM_MAGIC宏或厂商文档;offset是字节偏移,来自上一步定位的结果;value是要写入的字节值。
# 前置:确认接口已 down,否则部分驱动会拒绝写操作 ip link set dev eth0 down # 写入 6 个字节,magic 与 offset 必须替换成你实际测出来的值 # 假设原厂 MAC 位于 offset 0x40,magic 为 0x1234abcd ethtool -E eth0 magic 0x1234abcd offset 0x40 value 0x02 ethtool -E eth0 magic 0x1234abcd offset 0x41 value 0x11 ethtool -E eth0 magic 0x1234abcd offset 0x42 value 0x22 ethtool -E eth0 magic 0x1234abcd offset 0x43 value 0x33 ethtool -E eth0 magic 0x1234abcd offset 0x44 value 0x44 ethtool -E eth0 magic 0x1234abcd offset 0x45 value 0x55 # 回读校验,对比写之前和写之后的转储 ethtool -e eth0 offset 0x40 length 6 # 重启接口,观察内核读到的地址 ip link set dev eth0 up ip link show eth0 | grep link/ether参数说明:magic写错不会损坏数据,驱动会直接返回Invalid argument拒绝执行,这是它的设计目的,可以放心试。offset写错才是灾难,特别是写到校验和区域时,网卡下次上电自检失败会直接从 PCI 总线上消失,表现形式是lspci里看不到这块设备,系统日志里出现BAR 0: failed to map之类的报错。
value参数要注意,有些驱动的ethtool -E不接受裸字节,需要用value 0x02的十六进制形式;也有驱动支持length参数一次写多个字节,但兼容性不如逐字节稳。写之前务必确认接口处于 down 状态,写完之后不要立刻断电,让驱动把缓存刷到 NVM 里,等上十几秒再操作。
写完后ip link看到的地址如果还是旧的,不要慌,先ip link set dev eth0 down && up让驱动重新读一次 NVM。如果还是旧的,说明写入没生效,回头查magic和 offset 是否对准。
3.3 Windows 侧:注册表 NetworkAddress 与 PowerShell 批量下发
Windows 下没有ethtool这样的统一入口,常规做法是改驱动注册表项NetworkAddress。这个值由网卡驱动在初始化时读取,写进去之后禁用再启用适配器就会生效。它的持久性取决于驱动:部分企业级网卡驱动会把它落到 NVM,消费级网卡基本只保留在注册表里,重装驱动就丢了。
# 1. 列出所有网卡,记下 InterfaceDescription 和 ifIndex Get-NetAdapter | Select-Object Name, InterfaceDescription, MacAddress, ifIndex # 2. 定位该网卡在注册表中的 Class 子键(四位数字,如 0001) $cls = 'HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}' Get-ChildItem $cls | ForEach-Object { $desc = (Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue).DriverDesc if ($desc) { "$($_.PSChildName) $desc" } } # 3. 写入 12 位无分隔符的 MAC,然后重启适配器 $key = "$cls\0001" Set-ItemProperty -Path $key -Name NetworkAddress -Value '021122334455' -Type String Restart-NetAdapter -Name '以太网'NetworkAddress的值必须是 12 位连续十六进制,不带冒号或横线,写成02-11-22-33-44-55会被驱动忽略。改之前先把原值导出备份:如果原来没有这个键,说明驱动用的是出厂地址,回滚时直接删掉该键即可;如果原来有值,先记下来。
Set-NetAdapter -MacAddress也能改,但它走的是另一条路径,在某些驱动上等效于注册表写入,在另一些驱动上只是临时生效,行为不统一。批量场景下我更倾向直接用注册表 +Restart-NetAdapter,可控性强,也能配合组策略或配置管理工具下发。
注意:Windows 上如果装了厂商的网卡管理套件,它可能在服务启动时把
NetworkAddress重置成 NVM 里的值。改完先把这类服务停掉再验证。
3.4 虚拟化场景的静态 MAC 绑定
虚拟机克隆之后 MAC 重复是极常见的故障,表现为两台虚机抢同一个 IP、交换机 MAC 表来回抖动、网络时通时断。这类场景不需要硬刷,改配置文件里的静态绑定即可,风险最低。
<!-- libvirt/KVM 域配置中,把自动生成的 MAC 换成规划好的静态值 --> <interface type='bridge'> <mac address='52:54:00:aa:bb:cc'/> <source bridge='br0'/> <model type='virtio'/> </interface>52:54:00这一段是 QEMU 默认使用的本地管理前缀,第二位是 2,符合本地管理地址规范,自己规划时沿用这个前缀最省事。改完virsh define重新加载配置,再virsh domiflist确认生效。如果虚机内部又把 MAC 改回去了,检查是不是装了 cloud-init 或系统初始化脚本在开机时重新生成。
4. 批量改造:MAC 规划表、合法性校验和写入脚本
单台改 MAC 靠手敲就行,几十上百台就必须上流程。批量改造出问题从来不是因为命令写错,而是因为规划表本身就是错的:重号、越界、首字节不规范,这些问题在单台上看不出来,一上规模就是全网故障。所以批量改造的第一步是排号,第二步是校验,第三步才是写。
4.1 规划表怎么排:本地管理位与前缀约定
手工分配的 MAC 必须落在本地管理地址空间,也就是首字节的第二低位(从低位数)置 1,同时最低位(组播位)保持 0。满足这两个条件的首字节取值是x2、x6、xA、xE,例如02、06、0A、0E、12、16、1A、1E,一直到FE。
规划表建议按「机房 - 机柜 - 槽位」三段编码,把后 5 个字节拆成位置信息,这样一眼就能从 MAC 反推物理位置。比如约定首字节固定02,第二字节表示机柜号,第三字节表示 U 位,后三字节做序号,单机柜可容纳 1677 万种组合,够用且不冲突。
台账至少包含这几列:规划 MAC、设备序列号、网卡 PCI 地址、原厂 MAC、写入日期、操作人、备份文件路径。这份台账在设备返修、网卡更换、审计核查时是唯一凭据,别嫌麻烦。
4.2 用 Python 做写入前校验:四个必查项
写之前把整张规划表跑一遍校验,能挡掉 90% 的低级错误。必查四项:格式是否合法、组播位是否为 0、本地管理位是否为 1、全表是否重复。
import re from collections import Counter def normalize(mac: str) -> str: """把各种写法统一成 AA:BB:CC:DD:EE:FF""" mac = mac.strip().upper().replace('-', ':').replace('.', '') if ':' not in mac and len(mac) == 12: mac = ':'.join(mac[i:i + 2] for i in range(0, 12, 2)) if not re.fullmatch(r'([0-9A-F]{2}:){5}[0-9A-F]{2}', mac): raise ValueError(f'格式非法: {mac}') return mac def check_one(mac: str) -> list: raw = bytes.fromhex(mac.replace(':', '')) issues = [] if raw[0] & 0x01: issues.append('组播位为 1,内核会拒绝作为单播地址') if not raw[0] & 0x02: issues.append('本地管理位为 0,手工地址应置 1') if raw == b'\x00' * 6: issues.append('全零地址') if raw == b'\xff' * 6: issues.append('广播地址') return issues def check_all(macs: list) -> None: norm = [normalize(m) for m in macs] dup = {k: v for k, v in Counter(norm).items() if v > 1} for m in norm: for issue in check_one(m): print(f'[问题] {m}: {issue}') for m, n in dup.items(): print(f'[重复] {m} 出现 {n} 次') print(f'共校验 {len(norm)} 条,重复 {len(dup)} 条')normalize处理的是输入格式差异,有人写02-11-22,有人写021122334455,统一之后再比较才有意义。check_one里的两个位运算对应 MAC 地址规范:raw[0] & 0x01取最低位判断组播,raw[0] & 0x02取第二低位判断本地管理。check_all用Counter做全表查重,这一步在批量场景里最容易被跳过,也最容易出事。
4.3 Bash 批量写入与回读校验
校验通过后进入写入环节。脚本要做三件事:备份当前 NVM、逐字节写入、回读比对。任何一步失败就停下,不要继续往下写。
#!/usr/bin/env bash set -euo pipefail IFACE="${1:?用法: $0 <网口名> <MAC> <magic> <offset>}" TARGET_MAC="${2:?}" MAGIC="${3:?}" OFF="${4:?}" BACKUP_DIR="./nvm-backup" mkdir -p "$BACKUP_DIR" BACKUP="$BACKUP_DIR/${IFACE}-$(date +%Y%m%d%H%M%S).bin" # 1. 备份整段 NVM,失败立即退出 ethtool -e "$IFACE" raw on offset 0 length 512 > "$BACKUP" echo "[备份] $BACKUP ($(stat -c%s "$BACKUP") 字节)" # 2. 拆 MAC 成字节数组 IFS=':' read -r -a BYTES <<< "${TARGET_MAC//-/:}" # 3. 接口 down,逐字节写 ip link set dev "$IFACE" down for i in 0 1 2 3 4 5; do ethtool -E "$IFACE" magic "$MAGIC" offset $((OFF + i)) value "0x${BYTES[$i]}" echo "[写入] offset $((OFF + i)) = 0x${BYTES[$i]}" done ip link set dev "$IFACE" up sleep 3 # 4. 回读比对,不一致就报警并保留备份路径 ACTUAL=$(ip link show "$IFACE" | awk '/link\/ether/ {print toupper($2)}') echo "[回读] $ACTUAL 期望 $(echo "$TARGET_MAC" | tr 'a-f' 'A-F')" if [ "$ACTUAL" != "$(echo "$TARGET_MAC" | tr 'a-f' 'A-F')" ]; then echo "[失败] 回读与目标不一致,备份在 $BACKUP" exit 1 fi echo "[成功] $IFACE -> $ACTUAL"set -euo pipefail保证任何一条命令失败立即中断,避免写到一半继续跑。备份放在第一条,是因为写入一旦开始就没有回头路。逐字节循环里OFF + i对应 6 个连续偏移,value "0x${BYTES[$i]}"把冒号分隔的字节转成ethtool认的十六进制格式。
回读比对用ip link而不是ethtool -e,因为有些网卡的 NVM 写成功了但驱动缓存没刷新,ip link更能反映业务侧看到的结果。如果回读不一致,先ip link set dev eth0 down && up再读一次,仍不一致才判定失败。
批量跑的时候把网口名、MAC、magic、offset 做成 CSV,外层套一层while read循环,每台机器跑完把结果追加到日志文件,出问题的时候能一眼看出卡在哪台。
5. 避坑清单:五类翻车现场与回滚路径
硬刷这个操作,前面所有准备都是为了这一刻不出事。但出事的方式就那么几种,我把踩过的和见过的整理成五条,每条都按「现象、原因、解决」写,照着对号入座基本能定位。
5.1 写完重启又变回原厂地址
现象:命令全部返回成功,ip link也显示新地址,机器一重启就回到原厂 MAC。
原因:三种可能。一是ethtool -E的offset找错了位置,写到了 NVM 的空白区或者保留区,驱动下次加载读的还是原来那段;二是网卡本身不支持写 NVM,驱动在ethtool -E里做了伪实现,只在内存里改了缓存;三是机器上装了厂商网管代理,开机时按台账把 MAC 写回 NVM,把手工改的覆盖掉。
解决:先ethtool -e重新转储一遍,看目标偏移上的字节到底变没变。没变说明根本没写进去,回到第 2 章重新定位偏移;变了但重启仍回滚,停掉厂商管理服务再试一次。还有一种隐蔽情况是双口网卡的两个口共享同一段 NVM,改完 A 口之后改 B 口,B 口写入把 A 口那段覆盖了,这种必须两个口一起规划。
5.2 写一半断电,网卡从系统里消失
现象:写入过程中机器掉电或脚本被杀,重启后lspci里看不到这块网卡,dmesg有 PCI 枚举失败日志。
原因:NVM 的校验和区域被破坏。网卡上电时会校验 NVM 前若干字节的校验和,校验不过就拒绝加载固件,PCI 枚举阶段直接失败,系统里自然看不到设备。
解决:这是最严重的一种,但只要能进系统就还有救。把网卡拔下来插到另一台机器上(有些卡在另一台机器上能正常枚举,因为校验策略不同),用备份文件通过ethtool -E全量写回。更稳妥的方式是用厂商提供的 DOS/EFI 烧写工具,它们通常带-restore参数支持整段导入。救不回来的话只能换卡,所以第 2 章那份raw on备份不是可选项,是必做项。
5.3 两台机器 MAC 撞车,网络时通时断
现象:两台设备单独接网络都正常,同时接上就开始互相抢流量,ping 丢包率忽高忽低,交换机日志里能看到 MAC 地址漂移告警。
原因:规划表没有做全表查重,或者中途有人手工改了一台忘了同步台账。交换机按 MAC 建转发表,两个口报同一个 MAC 就会不停刷新表项,流量在两个口之间来回切换,表现就是时通时断。
解决:立刻在交换机上查show mac address-table | include <mac>,看这个 MAC 出现在哪几个口上,把其中一台先物理断开。然后用第 4 章的 Python 脚本做全表查重,确认还有没有其他重号。根治办法是把查重做成流程卡点,写入前必须跑一遍校验脚本并且把输出存档。
5.4 ethtool -E 直接报错
现象:Cannot set EEPROM data或Operation not supported。
原因:驱动没实现写回调,或者接口没 down,或者网卡处于安全启动/写保护状态。企业级网卡上写保护很常见,必须先在固件配置里解锁。
解决:先ip link set dev eth0 down重试一次,这是最常见的原因。还不行就看ethtool -i的驱动名,查这个驱动有没有实现set_eeprom,没有就换厂商工具。万兆以上的卡基本都要走厂商工具,ethtool那条路从一开始就是堵死的,不要在这上面浪费时间。
5.5 Windows 注册表改了没反应
现象:NetworkAddress值写进去了,Get-NetAdapter显示的还是原厂地址。
原因:子键序号认错,网卡实际在0002而你写了0001;或者驱动不读这个键;或者组策略把这个键锁定了。
解决:用DriverDesc匹配确认子键序号,别靠猜。确认写入后用Restart-NetAdapter而不是只禁用它,部分驱动要完整走一遍卸载重载流程。组策略锁定的情况在受管终端上很常见,gpresult /h能看到具体哪条策略在管,这种环境就不要硬碰了,走 IT 流程申请。
6. 验证与恢复:三遍回读加一份能救命的备份
写完不算完,我习惯做三遍验证,缺一遍都不放心。第一遍在系统里ip link show看运行时地址;第二遍ethtool -e转储目标偏移,确认 NVM 里的字节真的变了;第三遍最关键,换一种启动方式验证——用 U 盘进 PE 或者换个 Live 环境读一次,如果那边读出来也是新地址,说明确实写进了硬件,而不是留在驱动缓存里。这三遍做完,才算真正落盘。
第四步在交换机侧。连上网络之后,在交换机上查一次 MAC 表,确认这个地址学习到了预期的端口上。这一步能提前发现规划表重号的问题,比等到业务报障强得多。命令因设备而异,常见做法是show mac address-table address <mac>或者display mac-address <mac>,看端口和 VLAN 对不对。
恢复路径按损坏程度分三级,写在下面这张表里,建议和备份文件一起存档:
| 损坏程度 | 表现 | 恢复手段 |
|---|---|---|
| 仅地址写错 | 设备正常枚举,地址不对 | ethtool -E按备份逐字节写回 |
| 校验和破坏 | lspci看不到设备 | 换机器挂载后用厂商工具整段restore |
| NVM 物理损坏 | 任何工具都写不进 | 换卡,从台账结案 |
ethtool -E没有内置的restore参数,回滚是把备份文件用xxd拆回字节再逐字节写,或者用厂商工具的导入功能。我自己写了个小脚本放在备份目录里,读.bin文件按偏移写回,跑一次几十秒,比手动敲 512 条命令靠谱。
# 从备份 bin 文件恢复指定偏移区间的 6 个字节 BACKUP="./nvm-backup/eth0-20240101120000.bin" MAGIC="0x1234abcd" OFF=$((0x40)) for i in 0 1 2 3 4 5; do BYTE=$(xxd -p -s $((OFF + i)) -l 1 "$BACKUP") ethtool -E eth0 magic "$MAGIC" offset $((OFF + i)) value "0x${BYTE}" donexxd -p -s从指定偏移读指定长度并输出纯十六进制,-l 1表示读一个字节。这样备份文件就是唯一真相,不用另外维护一份「原厂 MAC 清单」。
提示:备份文件命名里带上网口 PCI 地址和日期,别只用
backup.bin。半年后回来找的时候,文件名是唯一能救命的信息。
从那以后我每次动 NVM 之前,都强制走一遍「转储、定位、校验、备份」四步,哪怕只是改一台机器、哪怕手上这块卡已经改过十几次。吃过一次断电的亏就知道,硬刷这件事没有第二次机会,备份是唯一的后悔药。希望帮到你。
本文还有配套的精品资源,点击获取