SOP — csh 环境注入双轨补齐(slurm-path / slurm_configless)¶
变更日期:2026-10-05 实施人:rain(Agent 执行) 状态:已完成,验收通过 缺口来源:
eda_tools_ins/design/docs/SLURM-CSH-INJECTION-GAP.md(【实测】) 归档目录:slurm_ins/slurm_csh_profile_20261005/
1. 背景¶
Slurm × Lmod 的登录环境注入一直存在单轨缺口:
/etc/profile.d/下 Lmod 侧已双轨(zzz_site_lmod.sh|.csh、00-modulepath.sh|.csh、modules.sh|.csh);- Slurm 侧只有 sh 单轨(
slurm-path.sh、slurm_configless.sh),缺.csh版; - 而 LDAP 域用户默认 shell =
/bin/csh(cy01、rain01等 8 个业务用户),csh 登录只读/etc/csh.login、/etc/csh.cshrc遍历的/etc/profile.d/*.csh,读不到*.sh。
后果【实测】:su - cy01 干净登录态下 sinfo/sbatch/srun/squeue 全部 Command not found,SLURM_CONF_SERVER 亦拿不到(configless 客户端取不到配置源)。临时补救只能靠 csh 用户手工 module load slurm。
2. 目标¶
- 让 csh/tcsh 用户与 bash 用户等效:登录即得
sinfo/squeue/sbatch/srun/scontrol,并拿到SLURM_CONF_SERVER; - 不改用户登录 shell,不改 Slurm 本体与
slurm.conf; - 幂等:复跑零变更、全跳过;PATH 不重复追加(同时修掉 bash 侧实测存在的「注入未判重」);
- 修正 modulefile
slurm/26.05.2.lua中「集群已有 /etc/profile.d 兜底」的失实文案(该表述对 csh 用户不成立)。
3. 前置条件¶
- root SSH 可达 6 台节点:控制
.16/.17、计算.18/.19/.20、提交.28; - 工程
.venv/与config/slurm_deploy.yaml就绪(configless: true、path_env.enabled: true); - 目标机
/etc/csh.login:34、/etc/csh.cshrc:55确实遍历/etc/profile.d/*.csh(已实测); - 目标机装有
csh/tcsh(/bin/csh)。
4. 影响范围¶
| 项 | 内容 |
|---|---|
| 主机 | .16 .17 .18 .19 .20 .28 共 6 台 |
| 文件 | /etc/profile.d/slurm-path.sh(改:加判重)、slurm-path.csh(增)、slurm_configless.csh(增,仅提交节点);.16 上 /opt/modulefiles/Core/slurm/26.05.2.lua(改 help 文案,随 NFS 供各节点) |
| 是否停服 | 否。不重启任何 daemon(--node-env/--submit-node 均不碰 daemon) |
| 在跑作业 | 不受影响:只改登录环境加载的 profile.d 与环境变量 |
| 窗口期 | 随时,无限制 |
5. 分步操作¶
本次变更以生成器代码为准(改
slurm_ins的渲染与部署逻辑),下发由部署器完成。以下给出等价的底层手工操作,供阅读、复核与手工复现;实现体路径见各步附注。幂等与错误处理由实现体保证,手工复现时需自行判重。
步骤 1:更新 /etc/profile.d/slurm-path.sh(加判重)¶
原实现直接 export PATH=... 前置,无判重,同一会话多次 source 后 PATH 内会出现多份 /usr/local/slurm/bin(实测 [已确认])。改为 case 判重:已在 PATH 中则不重复前置。该文件对 bash/POSIX 登录用户生效。
高危:覆盖既有 /etc/profile.d/slurm-path.sh 前先备份。
# 备份(高危动作前置)
cp -a /etc/profile.d/slurm-path.sh /etc/profile.d/slurm-path.sh.bak.$(date +%Y%m%d-%H%M%S)
# 写入(判重版)
cat > /etc/profile.d/slurm-path.sh <<'EOF'
# Slurm 命令路径(由 slurm 部署器写入,请勿手工修改)
SLURM_PREFIX="/usr/local/slurm"
case ":${PATH}:" in
*":${SLURM_PREFIX}/bin:"*) ;;
*) export PATH="${SLURM_PREFIX}/bin:${SLURM_PREFIX}/sbin:${PATH}" ;;
esac
unset SLURM_PREFIX
EOF
chmod 644 /etc/profile.d/slurm-path.sh
预期:文件权限 root:root 0644;重复 source 两次后 echo $PATH | tr ':' '\n' | grep -c '^/usr/local/slurm/bin$' 输出 1。
实现体:node_env_assets.py(render_profile_script)、node_env_deployer.py(_write_profile)。
步骤 2:新增 /etc/profile.d/slurm-path.csh¶
csh 侧必须单独一份。csh 无 export、不支持 2>&1;判重用 switch/case(与既有 render_site_profile_csh 同构),模式串在生成时即替换为字面路径,不依赖 csh 对 case 模式做变量展开。
cat > /etc/profile.d/slurm-path.csh <<'EOF'
# Slurm 命令路径(csh/tcsh 版,由 slurm 部署器写入,请勿手工修改)
# 由 /etc/csh.login 在登录时遍历 /etc/profile.d/*.csh 自动加载
switch (":${PATH}:")
case "*:/usr/local/slurm/bin:*":
breaksw
default:
setenv PATH "/usr/local/slurm/bin:/usr/local/slurm/sbin:${PATH}"
breaksw
endsw
EOF
chmod 644 /etc/profile.d/slurm-path.csh
预期:csh 登录后 which sinfo → /usr/local/slurm/bin/sinfo;source 两次后 PATH 前缀仍只 1 份。
坑:csh 命令里不得出现 $ 后紧跟引号(如正则 .../bin$"),会被 csh 当作变量引用而报 Illegal variable name。
实现体:node_env_assets.py(render_profile_script_csh)。
步骤 3:新增 /etc/profile.d/slurm_configless.csh(仅提交节点 .28)¶
提交节点无 slurmd,靠 SLURM_CONF_SERVER 向 slurmctld 取配置。csh 不读 *.sh,故须同源再渲染一份。值必须与 sh 版从同一变量(configless_server(),HA 时列出全部控制节点)渲染,避免两处硬编码漂移。
cat > /etc/profile.d/slurm_configless.csh <<'EOF'
# Auto-generated by slurm_deployer (do not edit manually)
setenv SLURM_CONF_SERVER "slurm-master-01:6817,slurm-master-02:6817"
EOF
chmod 644 /etc/profile.d/slurm_configless.csh
预期:su - cy01 -c "printenv SLURM_CONF_SERVER" 有值,且与 sh 版一致。
实现体:slurm_deployer.py(_configless_profile_content_csh)、submit_node_deployer.py(_write_config_source)。
步骤 4:修正 .16 上 modulefile slurm/26.05.2.lua 的 help 文案¶
原 help 写「集群已有 /etc/profile.d 兜底」——对 csh 用户不成立。改为分别点名 sh/csh 两份兜底文件。该 lua 由生成器产出,下手改生成器而非直接改 modulefile。
# 编辑 /opt/modulefiles/Core/slurm/26.05.2.lua 的 help 段为:
# ... sh/bash 用户由 /etc/profile.d/slurm-path.sh 兜底;
# csh/tcsh 用户由 /etc/profile.d/slurm-path.csh 兜底。...
预期:module help slurm 在 csh 与 bash 下均显示两份兜底文件。
实现体:module_env_assets.py(render_slurm_module)。
步骤 5:下发(实现体入口,附注)¶
.venv/bin/python main.py --config config/slurm_deploy.yaml --node-env
.venv/bin/python main.py --config config/slurm_deploy.yaml --submit-node
.venv/bin/python main.py --config config/slurm_deploy.yaml --module-env
预期:待执行变更 > 0、退出码 0、末尾 ✅ 部署完成 且健康校验通过。
6. 验证¶
判据(文档 §5 要求 + 本次实测结果):
| # | 命令 | 本轮实测 |
|---|---|---|
| 1 | su - cy01 -c "which sinfo sbatch srun squeue scontrol" |
五条全部命中 /usr/local/slurm/bin ✅ |
| 2 | su - cy01 -c "printenv SLURM_CONF_SERVER" |
slurm-master-01:6817,slurm-master-02:6817(与 sh 版同源) ✅ |
| 3 | su - cy01 -c "sinfo -N -l" |
正常列出节点与分区 ✅ |
| 4 | su - cy01 -c "printenv PATH" 中 /usr/local/slurm/bin 份数 |
6 台均为 1 ✅ |
| 5 | bash 侧 bash -lc 'command -v sinfo' 与份数 |
命中且份数为 1(不回归) ✅ |
| 6 | 幂等复跑 --node-env / --submit-node / --module-env |
第二次均为「待执行 0、全跳过、退出码 0」 ✅ |
6 台节点抽查(csh文件=1 sinfo=/usr/local/slurm/bin/sinfo bin份数=1):.16 .17 .18 .19 .20 .28 全部通过。
7. 回滚¶
系统侧(恢复变更前状态):
# 高危:删除本次新增的两个 csh 片段
rm -f /etc/profile.d/slurm-path.csh /etc/profile.d/slurm_configless.csh
# slurm-path.sh 恢复为「无判重」旧内容(旧渲染为 export PATH=... 直连)
# (内容见 backup/README.md 指向的源码备份,用旧 render_profile_script 重新渲染)
代码侧:从 backup/slurm_ins/ 恢复 5 个源文件的 .bak.20261005-135507,再复跑对应部署器。
备份位置与清单见 backup/README.md。回滚后验证:目标机 /etc/profile.d/ 下无 .csh 新文件、slurm-path.sh 哈希回到 078084a6f3fe...。
8. 风险说明¶
| 风险 | 缓解 |
|---|---|
覆盖 /etc/profile.d/slurm-path.sh 导致 bash 用户 PATH 异常 |
改动为「加判重」,语义等价且更稳;改造前后 PATH 均含同一前缀;有源码备份可回滚 |
| csh 判重语法在目标 csh 版本上行为差异 | 生成器输出已在本地 csh 实测(source 两次仅 1 份),并由部署器 verify() 逐台复检 |
| 两轨配置值漂移 | sh/csh 均由 configless_server() 同源渲染;验收第 2 条比对一致 |
SELinux 上下文:新文件由 SFTP 写入,ls 无 . 标记 |
profile.d 无特殊 context 要求,不影响加载;如需统一可 restorecon |
--module-env 下发连带修正 .16 上缺失的 synopsys/vcs/2023.12.lua |
该文件线上不存在、属新增补齐,无覆盖风险 |
附录:本次交付物¶
| 文件 | 说明 |
|---|---|
selftest_render.py |
离线自测:渲染 sh/csh 片段 + 本地 bash/csh 语法与判重验证 |
backup/README.md |
备份台账(5 个源文件 .bak.20261005-135507) |
本 SOP.md |
变更档案 |
来源:
/home/rain/Documents/slurm/slurm_ins/slurm_csh_profile_20261005/SOP.md| 最后更新:2026-10-05 14:10(由build/sync.py同步,请勿在站点侧修改)