SOP — IC617 幂等复跑实测(iscape 对已装目录的真实行为)¶
工程:
ic617_replay_20260927(验证工装)。本轮为 HANDOFF 待办 1「幂等复跑」的落地。 实测时间:2026-09-27 01:58 — 02:15(Asia/Shanghai)。 实现体:deployer.py+utils/(入口main.py)。
目录¶
- 背景
- 目标
- 前置条件
- 影响范围
- 分步操作
- 验证
- 回滚
- 风险说明 附录 A:实测数据 附录 B:结论与对既有文档的修正
1. 背景¶
ic617_install_20260926 的 SOP 目标 7 要求「幂等:复跑零变更、全跳过」,但该轮没有实现体
(SOP 第 5 章注明「实现体规划(尚未编写)」),因此该目标从未被实测。HANDOFF 待办 1 记录的
假设是「iscape 重跑会检测已装并跳过;尚未实测复跑零变更」。
本轮的实质问题因此不是「跑一次看看」,而是先证伪该假设:安装器对已装目标目录到底做什么。 结论会影响两件事——① 幂等验收判据该由谁保证;② 待办 2(介质与镜像清理)能否安全执行 (若复跑依赖镜像,镜像就不能删)。
2. 目标¶
变更完成后应达到的可验证状态:
| # | 目标状态 | 验证手段 |
|---|---|---|
| 1 | 取得 iscape 对已装目录的原生行为事实(跳过 / 覆盖 / 报错退出) | 安装器输出 + 退出码 + 与首次安装日志对比 |
| 2 | 量化复跑的实际写入范围(哪些文件/目录被改) | 跑前/跑后元数据快照 diff,按路径分类统计 |
| 3 | 确认 patch 未被覆盖、工具仍可用 | license_checkout 出现 checked out successfully(D.3 同款证据) |
| 4 | 六台客户端工具版本与变更前一致 | 六台 virtuoso -version |
| 5 | /tools 恢复变更前的只读稳态 |
六台 findmnt -no OPTIONS /tools 首项为 ro |
3. 前置条件¶
| 类别 | 检查项 | 判据 |
|---|---|---|
| 权限 | 操作机 → 六台 root 免密 | ssh root@<ip> hostname 六台全通 |
| 权限 | 执行端 root 身份 | id -u = 0 |
| 挂载 | /tools 可临时改 rw |
由人工 mount -o remount,rw /tools(见第 4 章) |
| 介质 | 镜像暂存完好 | 执行端 /var/tmp/ic617/04.IC06.17.700_Base 含 ic_index.sdx 与 Base_IC06.17.700_lnx86.sdp |
| 介质 | patch 恢复能力齐备 | /var/tmp/patch/07.cadence_patch/{sfk,cadence.pat} 在;/tools/_ic617_media/backup/pre_patch_libs_20260927-004833.tar.gz 在 |
| 安装器 | iscape 就位 | /opt/iscape/iscape.04.23-s010/bin/iscape.sh 可执行 |
| 业务 | 执行端无在跑作业 | Slurm squeue -h -w slurm-work-01 为空 |
| 空间 | 安装盘可用 | /tools 可用 ≥ 20G(实测 1223G) |
全部前置条件已落为实现体的预检查项(utils/precheck.py),其中挂载、介质、回滚资产三项为 BLOCK 级。
4. 影响范围¶
- 执行端:slurm-work-01(192.168.31.18),iscape 在此运行并写 NFS 共享盘。
- 变更对象:
/data/nfs/tools/cadence/virtuoso/IC617(安装树本体),六台经只读挂载共享可见。 - 人工动作:31.18 上
/tools由ro临时改rw,验证结束立即恢复ro; 该动作不由实现体代劳(2026-09-26 用户决策:挂载切换人工执行)。 - 是否停服:否。不动 license 服务、不改 NFS 导出、不重启节点。
- 窗口期:约 15 分钟(复跑本体约 2 分钟,快照与验证各占数分钟)。
- 不可逆点:无。本轮未覆盖 patch;即便被覆盖也可用
restore-patch子命令重跑sfk恢复(介质与备份均在),最坏情况按ic617_install_20260926/docs/SOP.md第 7 章用/var/tmp镜像重装。
5. 分步操作¶
实现体:
deployer.py(编排)、utils/precheck.py(门禁)、utils/replay_module.py(变更)、utils/snapshot.py(快照与比对)。下列 shell 为等价动作,供复核与手工复现。 幂等、三态探测、备份与失败处置由实现体保证。
步骤 0:预检查与门禁(只读)¶
汇总配置合法性、六台可达性、执行端 OS/时钟/调度器/权限/磁盘、镜像与回滚资产、/tools 挂载状态。
# 只读预检查(报告落 reports/,有 BLOCK 返回非 0)
cd ic617_replay_20260927 && .venv/bin/python main.py precheck
# 等价底层命令(示例)
ssh root@192.168.31.18 'findmnt -no OPTIONS /tools'
ssh root@192.168.31.18 'test -e /var/tmp/ic617/04.IC06.17.700_Base/ic_index.sdx && echo ok'
ssh root@192.168.31.18 'test -x /var/tmp/patch/07.cadence_patch/sfk && echo sfk-ok'
预期:唯一 BLOCK 为「/tools 当前为 ro」——这正是步骤 1 要人工解除的项。
失败判断:出现其他 BLOCK(镜像缺失、patch 介质缺失、SSH 不通)→ 先处置,不得进入变更。
步骤 1:/tools 临时改 rw(人工,高危)¶
复跑要写安装目录,NFS 客户端必须先有写权限。此步是唯一需要人工介入的红线动作, 前置检查在只读状态下必然报 BLOCK,属预期而非故障。
ssh root@192.168.31.18 'mount -o remount,rw /tools && findmnt -no OPTIONS /tools'
预期:首项由 ro 变 rw(rw,noatime,vers=4.2,...)。
失败判断:仍为 ro → 检查 NFS 导出与客户端权限,不得绕过继续。
步骤 2:跑前元数据快照(零变更基准)¶
对安装树取「类型 / 大小 / mtime / 路径」清单并落盘,作为判定零变更的基准。 选元数据而非全量哈希:安装器只要改写文件必然改变 mtime 与大小,而 11.6 万文件的全量哈希 在 NFS 上耗时远超收益。
ssh root@192.168.31.18 'find /tools/cadence/virtuoso/IC617 -xdev \
-printf "%y %s %T@ %p\n" 2>/dev/null | LC_ALL=C sort \
> /var/tmp/ic617_replay/snap_IC617_before_<ts>.meta; \
sha256sum /var/tmp/ic617_replay/snap_IC617_before_<ts>.meta; \
wc -l < /var/tmp/ic617_replay/snap_IC617_before_<ts>.meta'
预期:115881 行(实测),耗时约 30s。
失败判断:行数明显偏少 → 安装树不完整或 find 被截断,停止变更。
步骤 3:iscape 复跑(核心变更)¶
对同一个已装目标目录、用同一份介质重跑首次安装时的命令。参数取自首次安装:
archiveDirectory 指介质目录(含 .sdp/.sdx),installDirectory 指安装树。
坑:① 安装器需无 DISPLAY 环境;② 必须 < /dev/null 断开 stdin,否则安装器若在 batch 下
等待输入会挂住直到超时;③ 进程要 setsid 脱离会话(长任务),并以 rc 文件出现这一状态量
判定结束(不用固定 sleep);④ 启动命令的 ssh 通道也须 < /dev/null,否则后台进程持有通道 fd,
paramiko 侧会等到超时才返回(本轮首次执行即踩此坑,见附录 A.4)。
# 后台启动(inner 用 sh -c 承载;rc 文件出现即结束)
ssh root@192.168.31.18 "mkdir -p /var/tmp/ic617_replay && \
setsid nohup sh -c 'env -u DISPLAY /opt/iscape/iscape.04.23-s010/bin/iscape.sh -batch \
majorAction=InstallFromArchive \
archiveDirectory=/var/tmp/ic617/04.IC06.17.700_Base \
installDirectory=/tools/cadence/virtuoso/IC617 \
< /dev/null > /var/tmp/ic617_replay/replay_<ts>.out 2>&1; echo \$? > /var/tmp/ic617_replay/replay_<ts>.rc' \
>/dev/null 2>&1 < /dev/null & echo LAUNCHED"
# 轮询(就绪判据 = rc 文件出现)
ssh root@192.168.31.18 'cat /var/tmp/ic617_replay/replay_<ts>.rc; tail -n 5 /var/tmp/ic617_replay/replay_<ts>.out'
预期:rc=0;输出先列产品清单,随后直接
Installing: Install from CDROM(s) Successful → Done.,没有逐 kit 的 Installing: <kit> 行;
耗时约 2 分钟(首次安装约 8 分钟)。
失败判断:rc≠0 或输出含 ERROR → 先取日志定位;patch 若被覆盖走步骤 5 的判断分支。
步骤 4:跑后快照与差异分类¶
ssh root@192.168.31.18 'find /tools/cadence/virtuoso/IC617 -xdev \
-printf "%y %s %T@ %p\n" 2>/dev/null | LC_ALL=C sort \
> /var/tmp/ic617_replay/snap_IC617_after_<ts>.meta'
ssh root@192.168.31.18 'diff /var/tmp/ic617_replay/snap_IC617_before_<ts>.meta \
/var/tmp/ic617_replay/snap_IC617_after_<ts>.meta > /var/tmp/ic617_replay/diff_<ts>.txt; echo DIFF_RC=$?'
# 分类统计(类型分布、是否触及 lib 树)
ssh root@192.168.31.18 'grep -c "^< " /var/tmp/ic617_replay/diff_<ts>.txt; \
grep "^< " /var/tmp/ic617_replay/diff_<ts>.txt | cut -c3 | sort | uniq -c; \
grep -E "^[<>] " /var/tmp/ic617_replay/diff_<ts>.txt | grep -c "/tools.lnx86/lib/"'
预期(实测值见附录 A):差异 265 行/侧,其中触及 tools.lnx86/lib 的为 0 行——
即 patch 覆盖的库二进制未被改写。
失败判断:差异中出现 tools.lnx86/lib 下的文件 → 立即执行步骤 5 的恢复分支。
步骤 5:功能验证(判定 patch 是否仍生效)¶
sfk patch 的作用是让 license 能真正 checkout(D.3:patch 前 virtuoso 报
Unable to obtain ... license,patch 后成功)。因此license 能否 checkout 就是 patch 是否存活的功能判据。
坑:验证环境必须带齐 Rocky 9 适配要素 OA_UNSUPPORTED_PLAT=linux_rhel50_gcc48x 与
LD_PRELOAD=/lib64/libstdc++.so.6,否则 virtuoso 抛 OA sysname 错误、验证结论无意义;
另外 virtuoso -nograph 不会因 stdin EOF 自行退出,靠 timeout 结束,rc=124 属正常,
成败只看输出证据。
ssh root@192.168.31.18 'export CDS_LIC_FILE=5280@192.168.31.29 CDS_LIC_ONLY=1 CDS_AUTO_64BIT=ALL \
OA_UNSUPPORTED_PLAT=linux_rhel50_gcc48x LD_PRELOAD=/lib64/libstdc++.so.6; \
cd /tmp && timeout 120 /tools/cadence/virtuoso/IC617/tools.lnx86/dfII/bin/virtuoso -nograph \
< /dev/null > verify.out 2>&1; \
grep -aiE "licen[cs]e.*(checked out|successfully)" verify.out'
预期:Virtuoso Framework License (111) was checked out successfully. Total checkout time was 0.19s.
失败判断:出现 Unable to obtain / license 失败文案 → 判定 patch 被覆盖,执行
restore-patch(重跑 sfk rep -bylist cadence.pat -nowarn -yes -dir <install_dir>)后再复验。
步骤 6:/tools 恢复 ro(人工,高危)¶
ssh root@192.168.31.18 'mount -o remount,ro /tools && findmnt -no OPTIONS /tools'
ssh root@192.168.31.18 'for ip in 18 19 20 25 26 27; do ssh root@192.168.31.$ip \
"findmnt -no OPTIONS /tools | cut -d, -f1"; done'
预期:六台首项均为 ro(实测六台全 ro)。
失败判断:任一台仍 rw → 立即对该台 remount ro,避免共享盘长期暴露可写。
步骤 7:六台工具版本核对¶
for ip in 18 19 20 25 26 27; do ssh root@192.168.31.$ip 'export CDS_LIC_FILE=5280@192.168.31.29 \
CDS_LIC_ONLY=1 CDS_AUTO_64BIT=ALL OA_UNSUPPORTED_PLAT=linux_rhel50_gcc48x \
LD_PRELOAD=/lib64/libstdc++.so.6; cd /tmp && \
timeout 45 /tools/cadence/virtuoso/IC617/tools.lnx86/dfII/bin/virtuoso -version 2>&1 | grep -m1 "6.1.7"'; done
预期:六台均输出 @(#)$CDS: virtuoso version 6.1.7-64b 11/09/2015 12:45 (sjfnl165) $(实测一致)。
6. 验证¶
| 验证项 | 命令 | 判据 | 实测 |
|---|---|---|---|
| 零漂移 | .venv/bin/python main.py drift |
RC=0 | RC=0 |
| 安装态 | 同上(内部探测) | 主二进制存在、/tools = ro |
通过 |
| 工具可用性 | 同上(功能验证) | 版本命中 6.1.7 且 license checkout 成功 | 通过 |
| 六台一致性 | 步骤 7 | 六台版本串相同 | 通过 |
| 稳定态回归 | 六台 findmnt |
六台均 ro |
通过 |
7. 回滚¶
本轮未修改任何产品文件(差异 0 行涉及 tools.lnx86/lib),因此不需要文件级回滚。
按影响面排序的恢复路径:
| 情形 | 恢复动作 | 恢复后验证 |
|---|---|---|
| patch 被覆盖(license checkout 失败) | .venv/bin/python main.py restore-patch(等价:cd /var/tmp/patch/07.cadence_patch && ./sfk rep -bylist cadence.pat -nowarn -yes -dir /tools/cadence/virtuoso/IC617) |
步骤 5 复验出现 checked out successfully |
| 恢复 patch 仍失败 | 用 patch 前库备份还原:tar -xzf /tools/_ic617_media/backup/pre_patch_libs_20260927-004833.tar.gz -C /tmp/x && cp -a /tmp/x/. /tools/cadence/ |
同上 |
| 安装树整体损坏 | 按 ic617_install_20260926/docs/SOP.md 第 7 章:删安装目录后用 31.18 /var/tmp/ic617 镜像重跑 iscape → 再跑 sfk patch |
四工具 -version + license checkout |
/tools 忘记恢复 ro |
mount -o remount,ro /tools |
六台 findmnt 首项 ro |
备份位置:本轮未产生新备份文件(无文件被改写)。既有备份台账见
ic617_install_20260926/backup/README.md;本轮辅助制品(快照、diff、安装器日志)落在
执行端 /var/tmp/ic617_replay/ 与本工程 reports/,非备份性质,可随介质清理一并删除。
8. 风险说明¶
| # | 风险 | 影响 | 缓解 | 本轮实况 |
|---|---|---|---|---|
| 1 | 复跑覆盖已 patch 的二进制 | 工具失去 license,全部不可用 | 跑前确认 patch 介质与库备份齐备(BLOCK 门禁);命中即 restore-patch |
未发生(lib 差异 0 行) |
| 2 | 安装器 batch 模式等待交互输入 | 任务挂住直至超时 | 全程 < /dev/null;以 rc 文件判结束 |
未发生 |
| 3 | 长任务在 ssh 通道上挂死 | 控制端误判失败 | setsid + rc 文件 + 轮询;启动命令同时 < /dev/null |
首次踩坑(A.4),已修 |
| 4 | 忘记恢复 /tools 为 ro |
共享盘长期可写 | 步骤 6 单独成步 + 六台核验 | 已恢复 |
| 5 | 安装器在安装树内写日志(iscape_logs)被当作"零变更"误判 |
幂等结论失实 | 用元数据 diff 机械判定,不靠肉眼 | 已如实记录 265 行差异 |
| 6 | NFS 共享盘 IO 压力 | 影响同盘其他业务 | 快照为元数据遍历、复跑仅 2 分钟 | 未见异常 |
附录 A:实测数据¶
A.1 时间线¶
| 时刻 | 事件 |
|---|---|
| 01:58:43 | 预检查(ro 状态)→ 唯一 BLOCK:/tools 为 ro |
| 02:00:0x | 人工 remount rw → 预检通过 |
| 02:00:22 | 跑前快照完成:115881 文件,sha256 f0a512345993a13… |
| 02:00:22 | iscape 复跑启动 |
| 02:02:2x | iscape 结束,rc=0 |
| 02:03:01 | 跑后快照完成:115881 文件,sha256 0f714e4959a4491a… |
| 02:03:30 | diff:265 行/侧 |
| 02:04—02:12 | 功能验证(含两轮判据修正) |
| 02:12—02:15 | drift RC=0、六台版本核对、/tools 恢复 ro |
A.2 iscape 复跑输出(关键片段)¶
InstallScape Installer (Batch Mode) - 04.23.s10
The following products will be installed:
111:Cadence(R) Design Framework II
...(51 项产品清单)...
Installing: Install from CDROM(s) Successful
Done.
对比首次安装 iscape_ic617.log:其后跟数十行 Installing: <kit> <版本>(如
Installing: layout64b_lnx86 06.17-p048lnx86)后才是 Successful / Done.。
本轮无任何逐 kit 行 → 产品组件零安装。
A.3 差异分类(diff_manual_20260927-020329.txt)¶
| 指标 | 数值 |
|---|---|
| 差异行(左 / 右) | 265 / 265 |
| 类型分布 | 目录 44 / 文件 220 / 符号链接 1 |
涉及 tools.lnx86/lib 的差异行 |
0 |
| 变化内容性质 | 安装器收尾动作:install/tmp/* 临时与脚本、inca/files/IEEE_pure/ncrelocate.log、新增 cds.lib.ncreloc、iscape_logs 目录、若干目录 mtime |
A.4 本轮踩坑(实现体已修,文档留痕)¶
| 现象 | 根因 | 处置 |
|---|---|---|
启动命令返回 rc=-1、日志报「启动 iscape 失败」,但远端实际已执行完毕 |
后台进程继承 ssh 通道 stdin,paramiko 侧等不到 EOF,60s 超时后重试(并有重试副作用) | 启动命令补 < /dev/null;后续以 rc 文件判结束 |
virtuoso -version 报 OA sysname unknown |
验证环境漏配 OA_UNSUPPORTED_PLAT / LD_PRELOAD |
验证环境补齐 Rocky 9 适配要素 |
| license 验证"通过"实为假阳性 | 判据只匹配 license 关键词,未覆盖 OA 类 ERROR: |
判据收窄到 license 语境,并要求出现 checked out successfully |
附录 B:结论与对既有文档的修正¶
结论(实测)
- iscape 对已装目标目录复跑不重装任何产品 kit,退出码 0,行为是「识别已装 → 直接报成功」。
- 但不是严格零变更:它仍会重跑部分收尾步骤,改写约 220 个文件/目录(安装器临时区、 ncrelocate 产物、自身日志),并刷新 44 个目录 mtime。
- 复跑未触碰
tools.lnx86/lib,patch 保持有效,工具功能无退化(license checkout 成功)。 - 因此 SOP 目标 7「复跑零变更、全跳过」不能由安装器自身保证,必须由实现体的状态探测
(三态幂等)承担——原假设「iscape 重跑会检测已装并跳过」表述不准确,已在
ic617_install_20260926/docs/SOP.md附录 D.7 更正。 - 副产品结论:复跑依赖
/var/tmp/ic617镜像,故介质与镜像清理(HANDOFF 待办 2)应在 确认不再需要复跑/重装后退回镜像,不能在无镜像时依赖复跑做验证。
来源:
/home/rain/Documents/eda_tools_ins/Cadence/ic617_replay_20260927/docs/SOP.md| 最后更新:2026-09-27 02:15(由build/sync.py同步,请勿在站点侧修改)