Files
DCU_DesktopController/scripts/skip_host_snapshot.py
T
cbb e91d53e0fc feat(ecat): 启动后把 ecat_native 提到 RealTime;跳拍优化实验脚本与报告
- esp32_server: Popen 后外部 SetPriorityClass(RT/High),native 自设会被钳成 High
- 入库 skip_* 标定/实验脚本与 REPORT_ecat_skip_opt_20260917
- 前端 WIP:layout/app/polling/boot_ecat/index
- 不含 lab/skip_meter 原始采样与 preview 截图
2026-09-17 02:32:20 +08:00

127 lines
4.4 KiB
Python

#!/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())