跳转至

SOP — EDA 部署子工程「只读探测批量化」改造(probe_batch_20261008)

变更类型:存量工程工具层改造(只改只读探测的打包方式)。 执行人:Trae 子智能体;日期:2026-10-08;目标机:192.168.31.18/19/20/25/26/27/28。

1. 背景

5 个在用 EDA 部署子工程(Synopsys/rocky9_eda_compat、Synopsys/synopsys_pdk_saed32、 Cadence/pdk_integration、Cadence/ic617_replay、Synopsys/synopsys_install_2018)全部逐条 .run() 下发远端只读探测:无主机内拼壳、无跨主机并发、无 (host,cmd) 探测缓存。 实测 rocky9 单次只读 precheck 下发 36 条远端命令、墙钟 13.14 s,其中同一事实 (mountpoint -q /tools、test -f <制品>、license 端口)在多个检查项中被逐台各查一遍。

共享库 ~/py_public_modules/base_module.BaseModule 已完成新增能力(本次禁止修改共享库): query_on_host(带 (host,命令原文) 缓存)、probe_per_host(每台一条 shell 取回并回填缓存)、 invalidate_probe_cache(run_on_host/apply_change 后自动清空);共享库 precheck_module 另已内置 build_probe_shell/parse_probe_output/Prefetch 机制。

2. 目标(可验证)

  1. 5 个子工程的只读探测改为:同一主机拼一段 shell 一次往返、主机间并发、进程内吃缓存;
  2. 判定表达式、变更清单顺序与内容、变更类命令一律不变——预检查报告 / 漂移清单逐行一致;
  3. 各子工程 py_compile 通过;离线自测断言「新旧结果逐条一致 + 命令数下降」;
  4. 上机只读对照(precheck)给出命令数 / 墙钟实测,且报告内容新旧逐行一致。

3. 前置条件

  • 目标机 root 免密可达(本机 dell-R620 192.168.31.249/250,同网段;22 端口已验证 OPEN);
  • 各子工程 .venv 可用(共享库经 .pth 挂载);
  • 执行前已按文件整体备份到 probe_batch_20261008/backup/<子工程名>/(见 backup/README.md);
  • 只读:本轮仅执行 precheck(及各工程 probe_client_view 隔离调用),未执行任何变更子命令。

4. 影响范围

子工程 改动文件 是否影响变更路径
Synopsys/rocky9_eda_compat_20260928 deployer.py、utils/precheck.py、新增 utils/probe_batch.py 否(仅 sync_status/validate/drift 的探测通道)
Synopsys/synopsys_pdk_saed32_20260929 deployer.py、utils/precheck.py、新增 utils/probe_batch.py 否
Cadence/pdk_integration_20260927 deployer.py、utils/precheck.py、新增 utils/probe_batch.py 否
Cadence/ic617_replay_20260927 utils/precheck.py 否
Synopsys/synopsys_install_2018 utils/snps_state.py 否(仅客户端视图可见性探测并发化)

无停服、无窗口期要求;探测全部只读,对目标机无状态变更。共享库未改。

5. 分步操作(本次到底改了什么)

5.1 通用机制:utils/probe_batch.py(新增,rocky9 / synopsys_pdk_saed32 / pdk_integration 各一份)

只读探测的「记录 → 打包预取 → 命中缓存」三件套,复用共享库 precheck_module 的 build_probe_shell / parse_probe_output(逐条命令退出码不失真):

  • collect([task...]):顺序执行探测任务,只记录其下发的 run(host, cmd),不下发;
  • prefetch():按记录到的命令为每台主机拼一段 shell,用线程池主机间并发一次取回,回填 (host,cmd)->(rc,stdout);
  • run(host, cmd, timeout):预取过的命中缓存,未预取的回落逐条下发(语义与改造前一致,故漏配不会改结论)。

作为既有探测函数的 ssh_exec 传入即可,判定表达式零改动。

# 等价实现示意(实现体:utils/probe_batch.py)
pb = ProbeBatch(self.ssh)
pb.collect([lambda h=h: self._probe_host(h, pb) for h in hosts])  # 只记录命令
pb.prefetch()                                                     # 每台一条 shell(并发)
for h in hosts:
    items, unknown = self._probe_host(h, pb)                      # 命中缓存

坑:缓存键 = (host, 命令原文),故 collect 与真正判定必须由同一段代码产出命令文本 (本方案用「记录预演」保证逐字一致,不做手工复制命令文本,避免漂移)。prefetch 的整段 shell 超时取各命令超时之和(上限 1800s),单台连接失败时该台全部键记 -1(unknown)。

5.2 各子工程改动清单

子工程 文件:符号 改动
rocky9 utils/precheck.py EdaCompatPreCheck.static_probes(L29)+ check_tools_mount/check_compat_share/check_license_port(L59/78/103) 领域探测纳入基类批量预取,判定改走 self._probe(host, 键);命令文本集中到模块常量 _COMPAT_SHARE_RELS
rocky9 deployer.py _sha_state/_probe_host(L104/115,加 ssh 参数)、sync_status(L89)、validate(L315)、run_drift(L438) 漂移/验证/漂移子命令的逐台探测改为 ProbeBatch 记录+预取+命中
synopsys_pdk_saed32 utils/precheck.py static_probes(L31)+ 4 个挂载/端口检查(L171/189/203/221) 同上(domain_pdk_mount/domain_module_mount/domain_tools_mount/domain_license_port)
synopsys_pdk_saed32 deployer.py _probe_packages(L175,加 ssh 参数)、sync_status(L159)、validate(L453)、run_verify 库可见性抽查(L703) 同上
pdk_integration utils/precheck.py static_probes(L40)+ check_client(L171) 客户端 /pdk 挂载视图探测纳入批量(domain_client_mount)
pdk_integration deployer.py sync_status(L126)、validate(L402)、_client_checks(L437,加 ssh 参数)、cmd_drift(L508) 状态/验证/客户端检查经 ProbeBatch(底层为 LocalExecutor,本机走 run_local、远端走 SSH)
ic617_replay utils/precheck.py 抽出 4 个命令构造器(L66 起)+ static_probes(L103)+ 4 个领域检查(L120/157/188/213) 命令文本单点定义,领域探测纳入批量
synopsys_install_2018 utils/snps_state.py probe_client_view(L402) 逐台串行改 SSHExecutor.run_on_all(跨主机并发),判定与文案不变

5.3 未改动(明确不动)

  • 共享库 ~/py_public_modules/**;变更类命令(dnf install / rsync / chown / sed / mount 等);
  • 变更清单的生成顺序与内容、退出码语义、报告/漂移文案;
  • Cadence/ic25_install_20260924、Synopsys/synopsys_install_20260926(弃用)与设计/文档目录。

6. 验证

6.1 静态检查(已过)

# 5 个工程各自 .venv/bin/python -m py_compile(deployer/main/utils 全量)
# 结果:OK rocky9 / OK pdk_saed32 / OK pdk_integration / OK ic617_replay / OK synopsys_install_2018

6.2 离线自测(已过)

python3 /home/rain/Documents/eda_tools_ins/probe_batch_20261008/selftest.py

桩执行器模拟远端(不发真实命令),对「旧版备份 vs 新版工程」做 A/B,子进程隔离导入:

子工程 场景 旧往返 新往返 结果一致 命令数下降
rocky9_eda_compat_20260928 precheck 18 3 是 是
rocky9_eda_compat_20260928 drift 30 3 是 是
synopsys_pdk_saed32_20260929 precheck 16 4 是 是
ic617_replay_20260927 precheck 8 4 是 是

(结论:全部通过)

6.3 上机只读对照(已过;仅 precheck,跑完立即还原并 cmp 校验)

方法:记录日志中「开始执行命令」条数的前后差作为远端命令数;报告取 reports/precheck-*.md (剔除「生成时间」行后 diff)。每轮:存新版 → 跑新版 → 覆盖回旧版 → 跑旧版 → 还原新版 → cmp。

子工程 只读子命令 旧命令数 新命令数 旧墙钟 新墙钟 报告逐行一致 还原校验
rocky9_eda_compat_20260928 precheck 36 6 13.14 s 1.52 s 是 cmp OK
synopsys_pdk_saed32_20260929 precheck 23 7 7.10 s ≈1.5 s 是 cmp OK
Cadence/ic617_replay_20260927 precheck 12 8 2.58 s 1.86 s 是 cmp OK
Cadence/pdk_integration_20260927 precheck 12 6 3.29 s 1.56 s 是 cmp OK
Synopsys/synopsys_install_2018 probe_client_view(隔离调用,避开 31G 介质全量 cksum) — — 5.30 s 0.41 s 是(state=done,6 台 /tools 可见) 新文件未改,无需还原

备注:各工程日志为「按日切割」(TimedRotatingFileHandler),当天首次运行会触发一次轮转, 使「日志行差」口径失真;上表数据为轮转后复测所得。所有只读对照未对目标机产生任何变更。

7. 回滚

  • 备份位置:/home/rain/Documents/eda_tools_ins/probe_batch_20261008/backup/<子工程名>/, 台账见同目录 README.md(文件 600、目录 700)。
  • 逐文件覆盖回滚(工程非 git 管理):
BK=/home/rain/Documents/eda_tools_ins/probe_batch_20261008/backup
P=/home/rain/Documents/eda_tools_ins/Synopsys/rocky9_eda_compat_20260928
cp -a "$BK/rocky9_eda_compat_20260928/deployer.py"        "$P/deployer.py"
cp -a "$BK/rocky9_eda_compat_20260928/utils/precheck.py"  "$P/utils/precheck.py"
# 其余子工程按 backup/README.md 表逐条覆盖
  • 新增文件 utils/probe_batch.py(rocky9 / synopsys_pdk_saed32 / pdk_integration)删除即回滚。
  • 回滚后验证:各工程 py_compile 通过;precheck 报告与回滚前一致(判定逻辑未变)。

8. 风险说明

风险 缓解
预取命令文本与判定命令文本不一致 → 缓存不命中(退化为逐条,不影响正确性) collect 记录预演保证同源;未命中仅损失合并收益
整段 shell 超时不足 → 单台整批判为 unknown 超时取各命令超时之和(上限 1800s);unknown 仍按规范中止,不误改
单台连接失败被误判为「无需变更」 该台全部键记 -1(unknown),与逐条探测语义一致
并发过高触发 sshd MaxStartups 并发度沿用共享库默认 8(run_on_all 10),与既有用量一致
日志轮转导致命令数口径失真 上机对照在轮转后复测;口径已在本文注明

9. RUNBOOK 判定

本工程(及其 5 个在用子工程)现无 RUNBOOK.md。本次变更只改只读探测的打包方式, 未产生新的可复用交付物(各子工程仍是原有部署器,命令、配置与产物形态未变), 故本次不新增 RUNBOOK。若日后把这些子工程纳入日常运维手册,应另行产出(届时本判定失效)。

10. 已知项(遮蔽自检发现,未处置)

遮蔽自检 shared_lib_divergence_check.py --root /home/rain/Documents/eda_tools_ins 报出 工程内同名副本 1 处:

判定 模块 路径
已对齐 local_exec.py Cadence/ic25_install_20260924/utils/local_exec.py
  • 该副本与共享库版本的差异仅一行 docstring(功能等价),且 ic25_install_20260924 属 已弃用留档子工程(不在本次改造范围)。
  • 处置建议为「删除副本 + 改走 .pth」(其导入是 from local_exec import run_local, 删后自动回落共享库)。本次经用户裁定不改动留档工程,故登记于此,待该子工程退役时一并清理。
  • 其余 5 个在用子工程遮蔽检测均为 0 / 0。

来源:/home/rain/Documents/eda_tools_ins/probe_batch_20261008/SOP.md | 最后更新:2026-10-08 11:45(由 build/sync.py 同步,请勿在站点侧修改)