EDA Slurm Epilog 补全方案与执行 SOP¶
项目:EDA 存储标准化 —— Slurm 作业钩子补全 环境:Slurm 26.05.2 | 计算节点 k8s-node-01/02/03(192.168.0.5/6/7) 日期:2026-09-12
一、背景与目标¶
1.1 背景¶
现有 /usr/local/slurm/epilog_eda.sh 仅完成约 1/3 的职责(清 /tmp、/dev/shm、cgroup),
对 EDA 场景最关键的 License 回收、孤儿进程、SysV IPC、scratch 生命周期 均未覆盖,
且使用了 set -e(清理脚本一旦中途失败,后续清理全部跳过)。
1.2 目标¶
补全为覆盖 数字(VCS/Verdi)、模拟(Virtuoso/Spectre/ADS)、数模混合(AMS/Xcelium) 三类场景的通用 Epilog,并满足: 幂等、尽力执行、快速(≤120s)、可 dry-run、功能可开关、路径不硬编码。
二、Epilog 的完整职责(跨三场景通用性分析)¶
| # | 职责 | 数字 | 模拟 | 数模混合 | 说明 |
|---|---|---|---|---|---|
| 1 | 孤儿进程清理 | ✓ | ✓ | ✓ | 工具崩溃/被 kill 后残留,占 CPU/内存/GPU |
| 2 | System V IPC 清理 | ✓ | ✓ | ✓ | Cadence/Synopsys 信号量/共享内存,泄漏后耗尽 IPC |
| 3 | License 检测/回收 | ✓ | ✓ | ✓ | ★EDA 最关键:异常退出时 license 被占住 |
| 4 | 临时文件清理 | ✓ | ✓ | ✓ | /tmp、/dev/shm、$TMPDIR 写满致后续作业失败 |
| 5 | cgroup 残留清理 | ✓ | ✓ | ✓ | Slurm 一般自清,此处兜底 |
| 6 | scratch 生命周期标记 | ✓ | ✓ | ✓ | 打 .job_ok/.job_failed,交老化机制按保留期清理 |
| 7 | 审计与告警 | ✓ | ✓ | ✓ | 退出码/资源记录、失败现场保留提示 |
结论:七项职责全部跨三场景通用,无需按工具区分。真正的差异(保留哪些产物) 属作业脚本职责,不应放进 Epilog。
三、现状缺口分析(实测)¶
| 职责 | 原脚本 | 缺口 |
|---|---|---|
| 临时文件清理 | ✓ | 命名模式仅 slurm*/vcs*,覆盖不全 |
| cgroup 清理 | ✓ | — |
| 孤儿进程清理 | ✗ | 完全缺失 |
| SysV IPC 清理 | ✗ | 完全缺失 |
| License 处理 | ✗ | 注释写了"如果配置了 license check",但未实现 |
| scratch 标记 | ✗ | 完全缺失(新分层无人管) |
| 审计告警 | ✗ | 仅有简单 start/done 日志 |
set -e |
⚠ | 清理脚本用 -e 是隐患,中途失败即中断 |
另有配套缺口(本轮一并说明,未在本次部署范围):
- task_prolog_eda.sh 未注入 TMPDIR/LOCAL_SCRATCH
- 无 cron 老化脚本(scratch 保留期无人执行)
四、增强设计¶
4.1 七项职责与安全边界¶
| 职责 | 动作 | 安全边界(关键) |
|---|---|---|
| 1 孤儿进程 | pkill -u <JOB_UID> -x <工具名> |
仅杀本作业用户 + 精确进程名;GUI 进程默认排除 |
| 2 SysV IPC | ipcrm -s/-m |
仅清 owner = 本作业用户/UID 的项 |
| 3 License | lmutil lmstat 检测 |
默认 mode=check 只检测不回收,避免误伤并行会话 |
| 4 临时文件 | find <dir> -name "*<JOB_ID>*" -delete |
仅匹配含作业 ID 的路径(最保守) |
| 5 cgroup | rmdir <含ID目录> |
仅空目录兜底 |
| 6 scratch 标记 | touch .job_ok/.job_failed |
只标记,不删除(留复查窗口) |
| 7 审计 | 追加日志 | 只读作业信息,无系统变更 |
4.2 核心设计原则¶
- 不用
set -e(改set -uo pipefail):清理必须"尽力做完",单步失败不中断后续 - dry-run 感知:
EDA_EPILOG_DRY_RUN=1时只记录不执行 - 功能开关:7 项各自可开关(配置文件)
- 不硬编码:License 服务地址、lmutil 路径、scratch 根均走配置
- 超时保护:License 查询带
timeout,避免拖慢 Epilog
4.3 scratch 处理策略(回应"能否重建"判据)¶
Epilog → 只打标记(.job_ok / .job_failed)
老化机制 → 按保留期清理(成功短、失败长),给工程师留复查窗口
作业脚本 → 决定"留什么"(stage-out 结果;中间产物引导到 scratch)
判据是"能否重建"(波形/日志不可重建须留;csrc/simv 可重建可清),
但该判断只有工具/脚本有知识,Epilog 不猜。
五、风险说明与规避¶
| # | 风险 | 等级 | 规避措施 |
|---|---|---|---|
| 1 | 误杀 GUI 会话(VNC 中的 Virtuoso) | 高 | Xvnc/vncserver 默认不在清理清单,需显式启用 |
| 2 | 误清他人 SysV IPC | 中 | 仅清 owner = 本作业用户/UID |
| 3 | License 误回收活跃会话 | 高 | 默认 mode=check 只检测;recover 需运维确认后启用 |
| 4 | 误删非作业文件 | 中 | 仅匹配含作业 ID 的路径 |
| 5 | Epilog 超时被 Slurm 杀 | 中 | 各步快速执行;PrologEpilogTimeout=120 |
| 6 | 脚本语法错误致作业异常 | 高 | 部署时远端 bash -n 校验,失败自动回滚 |
六、分步操作(SOP)¶
前置条件¶
- 本机(rian,192.168.0.11)已配置到集群各节点 root 免密
- 集群无运行中作业(低峰窗口)
- 源文件:
epilog/epilog_eda.sh、epilog/epilog_eda.conf、epilog/nodes.conf
步骤 1:预演(不改任何系统状态)¶
cd /home/rian/Documents/slurm_ins/eda_storage_standardization/epilog
./deploy_epilog.sh --dry-run
步骤 2:确认节点清单¶
cat nodes.conf # 应为 192.168.0.5/6/7
步骤 3:真实部署(自动备份 + 语法校验)¶
./deploy_epilog.sh
说明:脚本按 SHA256 比对,远端一致则跳过(幂等);不一致则
cp -a <目标> <目标>.bak.<时间戳> 备份后传输并校验。
步骤 4:试运行验证(DRY-RUN 模式,不改系统)¶
./deploy_epilog.sh --verify
步骤 5:查看日志¶
ssh root@192.168.0.5 "tail -n 30 /var/log/slurm/epilog.log"
步骤 6(可选):启用 License 检测¶
需先将 lmutil 分发到计算节点,并核对 epilog_eda.conf 中 EDA_LMUTIL 路径。
当前默认
mode=check且 lmutil 不存在时自动跳过,不影响作业。
七、验证¶
| 验证项 | 命令 | 预期 |
|---|---|---|
| 语法 | bash -n epilog_eda.sh |
无输出 |
| 幂等 | 连续执行两次 ./deploy_epilog.sh |
第二次全部"跳过" |
| 部署一致 | sha256sum 本地/远端比对 |
一致 |
| 逻辑 | ./deploy_epilog.sh --verify |
输出 DRY-RUN 动作清单 |
| Slurm 集成 | 提交测试作业后看 epilog.log |
有本次 job 记录 |
八、回滚¶
cd /home/rian/Documents/slurm_ins/eda_storage_standardization/epilog
./deploy_epilog.sh --rollback
逻辑:查找各节点 epilog_eda.sh.bak.<时间戳> 中最新备份并恢复 + 语法校验。
手工回滚(单节点):
ssh root@192.168.0.5 "ls -1t /usr/local/slurm/epilog_eda.sh.bak.* | head -1"
ssh root@192.168.0.5 "cp -a /usr/local/slurm/epilog_eda.sh.bak.<TS> /usr/local/slurm/epilog_eda.sh"
应急降级(Epilog 异常时立即停用):
# slurm.conf 中注释 Epilog= 行后重载
ssh root@192.168.0.2 "sed -i 's|^Epilog=/usr/local/slurm/epilog_eda.sh|#&|' /usr/local/slurm/etc/slurm.conf && scontrol reconfigure"
九、第二阶段补全(已完成)¶
| # | 事项 | 状态 | 说明 |
|---|---|---|---|
| 1 | TaskProlog 注入环境变量 | ✅ | TMPDIR/LOCAL_SCRATCH/EDA_SCRATCH_LOCAL/EDA_SCRATCH_LUSTRE,并幂等创建作业工作区 |
| 2 | cron 老化脚本 | ✅ | scratch_aging.sh + /etc/cron.d/eda-scratch-aging(每日 03:30) |
| 3 | lmutil 分发 |
✅ | 分发到 3 计算节点 /usr/local/bin/lmutil,License 检测已生效 |
| 4 | scratch 布局校验 | ✅ | 权限 1777 + Lustre 条带 -c 3 -S 1M(幂等修复) |
| 5 | MDS 身份解析修复 | ✅ | 见第十章(关键阻塞项) |
9.1 老化策略(scratch 保留期)¶
| 位置 | 标记 | 保留期 | 参考时间 |
|---|---|---|---|
| 本地 SSD | .job_ok |
7 天 | 标记文件 mtime(≈ 作业结束时间) |
| 本地 SSD | .job_failed |
14 天 | 失败需更长现场保留 |
| 本地 SSD | 无标记 | 3 天 | 异常终止兜底 |
| Lustre | .job_ok / .job_failed / 无标记 |
14 / 30 / 7 天 | 容量更大,保留更久 |
为什么不是"作业一结束就删":必须给仿真工程师留复查窗口(看波形、复现问题、查覆盖空洞)。
判据是"能否重建"(波形/日志不可重建须留;csrc/simv 可重建可清),
但该判断只有工具/作业脚本有知识,Epilog 只打标记、不猜。
9.2 完整闭环¶
TaskProlog → 建 scratch + 注入 TMPDIR/SCRATCH 变量
↓ 作业运行(源在 NFS、中间产物在 scratch)
Epilog → 清临时 + 回收孤儿进程/SysV IPC + License 检测 + 打标记(.job_ok/.job_failed)
↓
cron(03:30) → scratch_aging.sh 按保留期清理
十、关键修复:Lustre MDS 身份解析¶
10.1 现象¶
TaskProlog 能在本地 SSD 建目录,但 Lustre 上创建被拒:
mkdir: cannot create directory '/lustre/eda_fs/scratch/users/lws01': Permission denied
而该目录权限已是 drwxrwxrwt(1777),且 root 可以创建。
10.2 根因(证据)¶
MDS(192.168.0.13)实测:
mdt.eda_fs-MDT0000.identity_upcall=/usr/sbin/l_getidentity
id lws01 → no such user
getent passwd 6001 → 无法解析
sssd 未运行;/etc/sssd/sssd.conf 不存在(但 nsswitch 已配 files sss)
因果链:客户端提交请求 → MDS 通过 l_getidentity upcall 解析 uid 6001 →
MDS 本地 NSS 无法解析(sssd 缺失)→ upcall 失败 → MDS 拒绝请求(EACCES)。
同一根因也解释了此前"chown 只能用数字 GID、服务端
ls显示数字"的现象—— 因为那台机器同时是 NFS Server 与 Lustre MDS。
10.3 修复¶
# 1) 安装 sssd
ssh root@192.168.0.13 "yum install -y sssd"
# 2) 从正常客户端同步配置(匿名绑定,不含密码)
ssh root@192.168.0.5 "cat /etc/sssd/sssd.conf" | ssh root@192.168.0.13 "cat > /etc/sssd/sssd.conf && chmod 600 /etc/sssd/sssd.conf"
# 3) 启动
ssh root@192.168.0.13 "systemctl enable --now sssd"
验证:id lws01 → uid=6001(lws01) gid=6000(cad) ✓
10.4 回滚¶
ssh root@192.168.0.13 "systemctl disable --now sssd; rm -f /etc/sssd/sssd.conf"
# nsswitch 的 'files sss' 可保留:sssd 缺失时自动退化到本地 files
行业标准意义:MDS / NFS Server 必须与计算节点处于统一身份体系(LDAP/AD), 否则分布式文件系统的身份 upcall 必然失败。这是通用要求,非本项目特有。
十一、验证记录(2026-09-12)¶
| 验证项 | 结果 |
|---|---|
| 部署幂等 | 第二次执行 18 项全部跳过(sha256/存在性比对) |
| 老化逻辑 | 造数据实测:.job_ok 10天→清、.job_failed 20天→清、无标记 5天→清、.job_ok 当天→保留 ✓ |
| scratch 布局 | node-01 修复后,node-02/03 自动识别"已符合"(Lustre 共享 + 幂等) |
| lmutil | v11.18.3.0 分发成功,Epilog 日志由"不可用"变为"License 处理完成 (mode=check)" |
| 全链路 | 提交真实作业 435:TaskProlog 注入 ✓ → 本地+Lustre scratch 自动创建 ✓ → Epilog 打 .job_ok ✓ |
| MDS 修复 | lws01 用户创建 Lustre 目录成功,属主 lws01:cad ✓ |
| 清理 | 测试文件与测试 scratch 已清除 |
十二、文件清单¶
12.1 本地源(eda_storage_standardization/epilog/)¶
| 文件 | 用途 | 部署目标 |
|---|---|---|
epilog_eda.sh |
增强版 Epilog 主脚本(7 项职责) | /usr/local/slurm/epilog_eda.sh |
task_prolog_eda.sh |
TaskProlog(注入 scratch/TMPDIR) | /usr/local/slurm/task_prolog_eda.sh |
scratch_aging.sh |
scratch 老化清理(按标记保留期) | /usr/local/slurm/scratch_aging.sh |
epilog_eda.conf |
功能开关与配置(不硬编码) | /usr/local/slurm/epilog_eda.conf |
scratch_aging.cron |
cron 定时任务(每日 03:30) | /etc/cron.d/eda-scratch-aging |
nodes.conf |
部署目标节点清单 | — |
deploy_epilog.sh |
幂等部署脚本(dry-run/备份/回滚) | — |
SOP.md |
本文档 | — |
12.2 关键日志(计算节点)¶
| 日志 | 用途 |
|---|---|
/var/log/slurm/epilog.log |
Epilog 执行日志 |
/var/log/slurm/epilog_audit.log |
作业审计(退出码、资源用量) |
/var/log/slurm/scratch_aging.log |
老化清理日志 |
/var/log/slurm/scratch_aging.cron.log |
cron 任务输出 |
来源:
/home/rain/Documents/slurm/eda_storage_standardization/epilog/SOP.md| 最后更新:2026-09-12 02:58(由build/sync.py同步,请勿在站点侧修改)