SOP — submit_node _sync_host 批量化 + 子命令基线补齐 + 附录 B 过期修正¶
主题目录:
slurm_ins/submit_node_batch_20261007/|执行日期:2026-10-07|类型:C 类(改实现体 + 修文档) 触发:核实「slurm_ins 的批量化改造是否全部完成、是否已沉淀可复用」时,发现两份附录 B 与代码不符、 子命令无任何实测基线,且唯一残留_sync_host未做
1. 背景¶
核实结果(只读审计 + file:line 复核):
sync_status_concurrency_20261007/SOP.md附录 B 把 8 处探测路径标为「尚未批量化」, 但代码里 7 处早已批量(用_run_per_host),清单已过期;conn_reuse_20261007/SOP.md附录 B 第 3 条抄了同一份过期清单。该过期清单已在本对话中误导过一次。- 唯一真正残留:
submit_node_deployer.py::_sync_host(每台 7~12 条串行_remote_query)。 - 所有实测数字只有主流程(
--dry-run墙钟 221.0 → 10.3 s):8 个子命令一个都没有独立基线。
2. 目标¶
| # | 目标 | 判据 |
|---|---|---|
| 1(B) | _sync_host 的只读探测每台一条 shell(回填探测缓存、调用点零改动) |
--submit-node 命令数下降;变更清单逐条一致 |
| 2(C) | 8 个子命令 + 主流程各出一次实测基线(命令数 / 墙钟) | 表格落盘,注明取数口径 |
| 3(A) | 两份过期附录 B 据实收缩 | 与代码一致,不再误导 |
| 4 | 命令文本单一来源(探测缓存键是 host+cmd,文本漂移即白做) | 离线自测断言「预取命令文本与 _sync_host 请求逐字一致」 |
3. 前置条件¶
- 工程根
/home/rain/Documents/slurm/slurm_ins,.venv可用; - 到 6 台节点(
.16–.20、.28)的 SSH 凭据沿用config/slurm_deploy.yaml; --module-env红线:执行前squeue必须为空 —— 本次跑前实测squeue -h | wc -l= 0 ✓;- 变更前完成 5.1 备份;验证全程
--dry-run(只读)。
4. 影响范围¶
| 项 | 内容 |
|---|---|
| 变更对象 | submit_node_deployer.py(主)、slurm_deployer.py(两处命令文本抽为单一来源)、两份附录 B、docs/HANDOFF.md |
| 改的是什么 | _sync_host 的探测方式;_remote_version / _missing_runtime_libs 各加一个可选 cmd 参数;判定与变更记录顺序、内容均不变 |
| 是否停服 | 否;验证全程只读 |
| 回滚风险 | 低:纯新增 + 内部实现替换,主流程实测 87 → 87 条、225/25/200 记录不变 |
5. 分步操作¶
5.1 备份(高危前置)¶
TOP=/home/rain/Documents/slurm/slurm_ins/submit_node_batch_20261007
STAMP=$(date +%Y%m%d-%H%M%S); mkdir -p "$TOP/backup/slurm_ins"
cd /home/rain/Documents/slurm/slurm_ins
for f in submit_node_deployer.py slurm_deployer.py; do
cp -a "$f" "$TOP/backup/slurm_ins/$f.bak.$STAMP"; done
预期:2 个 .bak.20261007-215118。
5.2 命令文本抽为单一来源(slurm_deployer.py)¶
探测缓存以 (host, cmd) 为键 —— 预取与调用两处文本必须逐字相同,否则预取白做。
故把两处内联文本抽成静态方法,两处共用:
# 概念等价:命令文本只在一处定义
# _version_cmd(bin) -> "{bin} --version 2>&1 | head -1"
# _runtime_libs_cmd(dir) -> "cd '{dir}' … | grep 'not found' | awk '{print $1}' | sort -u"
# _remote_version(host, bin_path, cmd=None) ← cmd 供预取复用同一文本
# _missing_runtime_libs(host, install_dir, cmd=None) ← 同上
坑:cmd 必须默认 None(保持既有调用点行为),probe = cmd or self._xxx_cmd(...)。
5.3 _sync_host 改为预取 + 缓存命中(submit_node_deployer.py)¶
# 概念等价(Python 侧实现,非 shell):每台一条 shell 一次往返
# _sync_probe_cmds(...) → {键: 命令}(只读探测的唯一来源:逐包 rpm -q / id -u /
# systemctl is-active munge / 版本 ×2 / readlink /
# ldd 缺库 / configless 或 slurm.conf 摘要)
# _prefetch_sync_probes(hosts, cmds) → 每台 _kv_script 一段 shell,_parse_kv 拆回,
# 回填 self._query_cache[(host, cmd)]
# sync_status(): 先 prefetch,再逐台 _sync_host(..., cmds)
坑(必须留痕):
- 回填的是 (host, 命令原文) 键,不是 键;_sync_host 的 _remote_query 才能命中;
- 「一次调用传多条命令」不算合并(exec_linux 逐条 run_cmd)——必须拼成一段 shell;
- _kv_script 的分段标记是 @@键;_parse_kv 按此拆回;
- 变更类命令不动:本次只搬只读探测。
5.4 离线自测(上机前)¶
cd /home/rain/Documents/slurm/slurm_ins
.venv/bin/python -m py_compile submit_node_deployer.py slurm_deployer.py && echo COMPILE_OK
.venv/bin/python submit_node_batch_20261007/selftest.py
预期:COMPILE_OK + SUBMIT_NODE_BATCH_SELFTEST_OK。
坑:本工程 deployer.py 用相对导入,自测必须以 slurm_ins.<mod> 方式导入;
载入 backup 版旧模块时名字也要带包前缀(slurm_ins._old_...),否则相对导入解析失败。
5.5 上机对照 + 子命令基线(C)¶
cd /home/rain/Documents/slurm/slurm_ins
bash submit_node_batch_20261007/verify_batch.sh # 旧/新两轮 + 变更清单对照
8 个子命令基线(逐条基线,各跑一次 --dry-run):
declare -A LOGS=( [--node-env]=logs/slurm_node_env_deploy.log \
[--module-env]=logs/slurm_module_env_deploy.log \
[--storage-layout]=logs/slurm_storage_layout_deploy.log \
[--scratch-gc]=logs/slurm_scratch_gc_deploy.log \
[--local-scratch]=logs/slurm_local_scratch_deploy.log \
[--health-ensure]=logs/slurm_health_deploy.log \
[--user-mgmt]=logs/slurm_usermgmt_deploy.log \
[--submit-node]=logs/slurm_submit_node.log )
for m in "${!LOGS[@]}"; do L=${LOGS[$m]}; S0=$(wc -l < "$L"); T0=$(date +%s.%N)
.venv/bin/python main.py --config config/slurm_deploy.yaml --dry-run $m >/dev/null 2>&1
echo "$m cmds=$(tail -n +"$((S0+1))" "$L" | grep -c '命令执行完成')"
done
口径:命令数 = 该子命令日志里 命令执行完成 行数(= run_cmd 逐条执行数)。
6. 验证¶
验证一:语义等价
- 离线:新旧 _sync_host 在同一模拟远端下 _add_change 记录逐条一致;且「预取命令文本
与 _sync_host 实际请求逐字一致」;非 configless 与 configless 两个分支、以及「未达标场景」全部覆盖;
- 上机:--submit-node 变更记录 31 条,新旧排序后完全一致、顺序差异 0;
主流程 225 条记录、待执行 25 / 幂等 200,新旧完全相同;
验证二:命令数与墙钟【已确认】
| 子命令 | 命令数 | 墙钟 s | rc |
|---|---|---|---|
| --submit-node | 37 → 26(-29.7%) | 18.0 → 12.3(-31.7%) | 0 |
| 主流程(无子命令) | 87(新旧同为 87) | 11.4 | 0 |
| --storage-layout | 52 | 8.0 | 0 |
| --scratch-gc | 27 | 6.0 | 0 |
| --module-env | 20 | 4.7 | 0 |
| --node-env | 18 | 7.2 | 0 |
| --health-ensure | 15 | 12.2 | 0 |
| --user-mgmt | 14 | 4.3 | 0 |
| --local-scratch | 0 ※ | 6.7 | 0 |
※ --local-scratch 的日志里没有 命令执行完成 行(其远端调用不经该日志路径),
该数字不可比,其它子命令口径一致。8 个子命令合计 ≈ 183 条。
验证三:幂等 —— 各子命令 --dry-run 均 rc=0;--submit-node 31/0/31 全跳过。
✅ 附带发现(2026-10-11 结案):docs/HANDOFF.md 记的「主流程远端命令 864 → 18」,
两种口径实测均为 87(命令执行完成)/ 90(exec_linux),墙钟则相符(11.4 vs 10.3 s);
原数字不可复现、疑似跨工程抄写。已按实测订正 HANDOFF(结案口径见 ../efficiency_wrapup_20261011/README.md)。
失败判断:变更记录出现实质差异(非顺序),或 py_compile / 自测失败 → 按第 7 章回滚。
7. 回滚¶
- 备份位置:
submit_node_batch_20261007/backup/slurm_ins/,台账见同目录backup/README.md。 - 回滚步骤:
cd /home/rain/Documents/slurm/slurm_ins
BAK=submit_node_batch_20261007/backup/slurm_ins
for f in submit_node_deployer.py slurm_deployer.py; do cp -a "$BAK/$f".bak.* "$f"; done
- 回滚后验证:
py_compile+--submit-node --dry-run(命令数回到 37、变更记录仍 31 条)。 - 回滚触发条件:变更记录出现实质差异;
--submit-node报错;主流程命令数或记录数变化。
8. 风险说明¶
| 风险 | 缓解 |
|---|---|
| 命令文本漂移 → 预取不命中(白做) | 文本抽为单一来源(_version_cmd / _runtime_libs_cmd / _sync_probe_cmds);离线自测逐字比对 |
回填键写错(写成 键 而非 (host, 命令)) |
离线自测断言「预取后零新增远端调用」 |
给 _remote_version / _missing_runtime_libs 加参数破坏既有调用 |
新参数默认 None,不传时行为与原来完全一致;主流程回归 87→87 条、225/25/200 不变 |
--local-scratch 等子命令的基线口径不一致 |
已在第 6 章显式标注该行不可比,不冒充 |
| 附录 B 修正后丢失历史信息 | 用「已全部完成 + 指针」替换,原文保留在各主题 SOP 的改前快照(backup)中 |
附录 A 交付物清单¶
| 文件 | 说明 |
|---|---|
SOP.md |
本文件 |
selftest.py |
离线自测(命令文本一致性 / 新旧等价 / 命令数 / configless 分支) |
verify_batch.sh |
旧新两轮上机对照(含变更清单比对) |
backup/slurm_ins/ |
2 个改造前文件快照 |
backup/README.md |
备份台账 |
| 变更的工程文件 | submit_node_deployer.py、slurm_deployer.py |
| 修正的文档 | sync_status_concurrency_20261007/SOP.md 附录 B、conn_reuse_20261007/SOP.md 附录 B、docs/HANDOFF.md |
附录 B 子命令基线(C 的产出,供后续任何优化做 before/after)¶
见第 6 章「验证二」表。此前 8 个子命令一个数字都没有;本表是它们的第一份基线。 后续再动任一子命令,用 5.5 的同法取 before/after 即可。
来源:
/home/rain/Documents/slurm/slurm_ins/submit_node_batch_20261007/SOP.md| 最后更新:2026-10-11 21:15(由build/sync.py同步,请勿在站点侧修改)