HPC服务器资源分配自动化脚本异常:分配资源被自动收回
问题原因
- 后台执行
salloc触发资源回收:
脚本中用salloc -A ... &将资源分配命令丢到后台运行,salloc本质是交互式工具,默认会在分配节点上启动登录shell。后台运行时该shell因无终端绑定会快速退出,Slurm检测到节点无活跃作业,立刻收回资源。 - 环境变量无法跨shell传递:
SLURM_NODELIST是salloc启动的子shell专属变量,父脚本的shell无法直接读取,导致NODE=$SLURM_NODELIST得到空值,脚本直接退出,进一步终止salloc进程加速资源回收。 - 固定等待时间不可靠:
sleep 10属于硬编码等待,集群资源分配速度不确定,既不能保证节点分配完成,也解决不了变量传递的核心问题。
解决方案
方案1:让salloc直接执行节点任务(推荐)
利用salloc可直接指定运行命令的特性,让Slurm保持资源直到任务结束,同时在salloc的环境中直接使用SLURM_NODELIST:
#!/bin/bash salloc -A naiss2025-22-391 -t 1:00:00 -p shared -N 1 << EOF NODE=\$SLURM_NODELIST echo "Node allocated: \$NODE" # 在登录节点建立SSH隧道 ssh -NfL 8889:localhost:8889 "\$NODE" # 在分配节点启动JupyterLab source ~/Private/chandra/my_env/bin/activate jupyter lab --no-browser --port=8889 --ip=127.0.0.1 EOF
注意:EOF内部的变量需加转义符\$,避免被父shell提前解析。
方案2:用srun替代salloc(更简洁)
srun可直接在分配节点执行命令,通过捕获hostname输出获取节点名:
#!/bin/bash # 分配节点并获取节点名 NODE=$(srun -A naiss2025-22-391 -t 1:00:00 -p shared -N 1 hostname) if [ -z "$NODE" ]; then echo "Failed to get node name." exit 1 fi echo "Node allocated: $NODE" # 建立SSH隧道 ssh -NfL 8889:localhost:8889 "$NODE" # 在节点启动JupyterLab ssh "$NODE" << EOF source ~/Private/chandra/my_env/bin/activate jupyter lab --no-browser --port=8889 --ip=127.0.0.1 EOF
srun hostname会在分配节点执行命令并返回节点名,父shell可直接捕获,Slurm会保持资源直到JupyterLab进程结束。
方案3:通过作业ID查询节点信息(备选)
若必须用salloc,可先获取作业ID,再用sacct查询节点:
#!/bin/bash # 启动salloc并记录进程ID salloc -A naiss2025-22-391 -t 1:00:00 -p shared -N 1 & SALLOC_PID=$! # 等待作业分配完成(可根据集群情况调整等待时间) sleep 5 # 获取最新作业ID JOB_ID=$(squeue -u $USER -h -o "%i" --sort=-i | head -n1) # 查询节点名 NODE=$(sacct -j $JOB_ID -n -o NodeList) if [ -z "$NODE" ]; then echo "Failed to get node name." kill $SALLOC_PID exit 1 fi echo "Node allocated: $NODE" # 建立隧道并启动JupyterLab ssh -NfL 8889:localhost:8889 "$NODE" ssh "$NODE" << EOF source ~/Private/chandra/my_env/bin/activate jupyter lab --no-browser --port=8889 --ip=127.0.0.1 EOF # 终止salloc进程 kill $SALLOC_PID
该方案需处理作业状态查询,可靠性不如前两种。
内容的提问来源于stack exchange,提问作者Ep1c1aN
相关产品推荐
相关产品推荐

