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. 目标(可验证)¶
- 5 个子工程的只读探测改为:同一主机拼一段 shell 一次往返、主机间并发、进程内吃缓存;
- 判定表达式、变更清单顺序与内容、变更类命令一律不变——预检查报告 / 漂移清单逐行一致;
- 各子工程
py_compile通过;离线自测断言「新旧结果逐条一致 + 命令数下降」; - 上机只读对照(
precheck)给出命令数 / 墙钟实测,且报告内容新旧逐行一致。
3. 前置条件¶
- 目标机 root 免密可达(本机
dell-R620192.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同步,请勿在站点侧修改)