#!/usr/bin/env python3 # -*- coding: utf-8 -*- """快照当前主机侧可回滚现场:I210 高级属性、中断亲和、ecat 进程。""" from __future__ import annotations import json import os import subprocess import sys import time ROOT = os.path.normpath(os.path.join(os.path.dirname(__file__), "..")) LAB = os.path.join(ROOT, "lab", "skip_meter") def ps(cmd: str) -> str: r = subprocess.run( ["powershell", "-NoProfile", "-Command", cmd], capture_output=True, text=True, encoding="utf-8", errors="replace", ) return (r.stdout or "") + (("ERR:" + r.stderr) if r.stderr else "") def main() -> int: os.makedirs(LAB, exist_ok=True) snap = {"ts": time.time(), "host": os.environ.get("COMPUTERNAME")} snap["adapters"] = ps( "Get-NetAdapter | Select-Object Name,InterfaceDescription,LinkSpeed,Status," "ifIndex,MacAddress | ConvertTo-Json -Compress" ) # I210 specifically snap["i210"] = ps( "Get-NetAdapter | Where-Object {$_.InterfaceDescription -match 'I210'} | " "Select-Object Name,ifIndex,Status,LinkSpeed | ConvertTo-Json -Compress" ) # advanced properties (restore-able) snap["i210_adv"] = ps( "Get-NetAdapterAdvancedProperty -Name '以太网 2' -ErrorAction SilentlyContinue | " "Select-Object Name,DisplayName,DisplayValue,RegistryKeyword,RegistryValue | " "ConvertTo-Json -Compress" ) # interrupt moderation / RSS / power for kw in ( "*InterruptModeration", "*ReceiveBuffers", "*TransmitBuffers", "*EEE", "*EnergyEfficient", "*FlowControl", "*PriorityVLANTag", "*TCPChecksumOffload*", "*IPChecksumOffload*", "*VMQ", "*RSS", "*InterruptModerationRate", ): snap[f"adv_{kw.strip('*').replace('*','_')}"] = ps( f"Get-NetAdapterAdvancedProperty -Name '以太网 2' -ErrorAction SilentlyContinue | " f"Where-Object {{$_.RegistryKeyword -like '{kw}'}} | " f"Select-Object RegistryKeyword,DisplayValue,RegistryValue | ConvertTo-Json -Compress" ) snap["power"] = ps( "Get-NetAdapterPowerManagement -Name '以太网 2' -ErrorAction SilentlyContinue | " "Select-Object Name,AllowComputerToTurnOffDevice,WakeOnMagicPacket," "WakeOnPattern,DeviceSleepOnDisconnect | ConvertTo-Json -Compress" ) snap["ecat_proc"] = ps( "Get-Process ecat_native -ErrorAction SilentlyContinue | " "Select-Object Id,Path,StartTime,CPU,WorkingSet | ConvertTo-Json -Compress" ) snap["ecat_cmdline"] = ps( "Get-CimInstance Win32_Process -Filter \"Name='ecat_native.exe'\" | " "Select-Object ProcessId,CommandLine | ConvertTo-Json -Compress" ) # interrupt affinity via Get-NetAdapterInterrupt? not always available snap["msi_affinity"] = ps( "Get-NetAdapterAdvancedProperty -Name '以太网 2' -ErrorAction SilentlyContinue | " "Where-Object {$_.DisplayName -match 'Interrupt|Affinity|RSS|Moderation|Buffer|Energy|Green|Flow|Offload'} | " "Select-Object DisplayName,DisplayValue,RegistryKeyword | ConvertTo-Json -Compress" ) # CPU topology quick snap["cpu"] = ps( "$env:NUMBER_OF_PROCESSORS; (Get-CimInstance Win32_Processor | " "Select-Object Name,NumberOfCores,NumberOfLogicalProcessors | ConvertTo-Json -Compress)" ) out = os.path.join(LAB, f"host_snap_{int(time.time())}.json") with open(out, "w", encoding="utf-8") as f: json.dump(snap, f, ensure_ascii=False, indent=2) # also human-readable restore snippet lines = [] lines.append("# Host snapshot restore notes") lines.append(f"time={snap['ts']}") lines.append("## I210 adapter advanced (raw)") lines.append(snap.get("i210_adv", "")[:8000]) lines.append("## power") lines.append(snap.get("power", "")[:4000]) lines.append("## ecat cmdline") lines.append(snap.get("ecat_cmdline", "")[:2000]) txt = os.path.join(LAB, f"host_snap_{int(snap['ts'])}.txt") with open(txt, "w", encoding="utf-8") as f: f.write("\n".join(lines)) print("I210:", snap.get("i210", "")[:500]) print("CMDLINE:", snap.get("ecat_cmdline", "")[:800]) print("ADV keys sample:") print(snap.get("msi_affinity", "")[:2500]) print("WROTE", out) print("WROTE", txt) return 0 if __name__ == "__main__": raise SystemExit(main())