如何获取用于 SLURM 作业的脚本的原始位置?

5 浏览
0 Comments

如何获取用于 SLURM 作业的脚本的原始位置?

我正在使用脚本启动SLURM作业,并且脚本必须根据其位置来工作,该位置在脚本本身中通过SCRIPT_LOCATION=$(realpath $0)获得。但是SLURM会将脚本复制到slurmd文件夹并从那里启动作业,这会搞乱后续操作。

在脚本被移动/复制之前,是否有任何选项可以获取用于slurm作业的脚本位置?

脚本位于网络共享文件夹/storage/software_folder/software_name/scripts/this_script.sh,它必须执行以下操作:

  1. 获取自己的位置
  2. 返回software_name文件夹
  3. software_name文件夹复制到节点上的本地文件夹/node_folder
  4. 从复制的文件夹/node_folder/software_name/scripts/launch.sh运行另一个脚本

我的脚本是:

#!/bin/bash
#SBATCH --nodes=1
#SBATCH --partition=my_partition_name
# 获取software_name的位置
SHARED_PATH=$(dirname $(dirname $(realpath $0)))
# 从路径中分离出software_name
SOFTWARE_NAME=$(basename $SHARED_PATH)
# 要复制项目的目标位置
LOCAL_SOFTWARE_FOLDER='/node_folder'
# 目标的修正路径
LOCAL_PATH=$LOCAL_SOFTWARE_FOLDER/$SOFTWARE_NAME
# 从网络存储复制软件文件夹到本地
cp -r $SHARED_PATH $LOCAL_SOFTWARE_FOLDER
# 运行脚本
sh $LOCAL_PATH/scripts/launch.sh

当我在节点本身上运行它(不使用SLURM)时,它运行得很完美:sh /storage/software/scripts/this_script.sh

如果使用SLURM运行它,例如:sbatch /storage/software/scripts/this_script.sh,它被分配给一个节点,但是:

  • 在运行之前,它会被复制到/var/spool/slurmd/job_number/slurm_script,这导致$(dirname $(dirname $(realpath $0)))返回/var/spool/slurmd

在脚本启动时是否有可能获得原始位置(/storage/software_folder/software_name/)?

P.S. 所有机器都运行Fedora 30(x64)

更新1

有人建议以sbatch -D /storage/software_folder/software_name ./scripts/this_script.sh方式运行,并在脚本中使用SHARED_PATH="${SLURM_SUBMIT_DIR}"

但是会出现错误sbatch: error: Unable to open file ./scripts/this_script.sh

我还尝试使用绝对路径:sbatch -D /storage/software_folder/software_name /storage/software_folder/software_name/scripts/this_script.sh。它尝试运行,但是:

  • 在这种情况下,它仅将指定的文件夹用于创建输出文件
  • 软件仍然无法运行
  • 尝试在脚本中使用echo "${SLURM_SUBMIT_DIR}"会打印/home/username_who_started_script而不是/storage/software_folder/software_name

还有其他建议吗?

更新2:

还尝试在脚本中使用#SBATCH --chdir=/storage/software_folder/software_name,但在这种情况下,echo "${SLURM_SUBMIT_DIR}"返回/home/username_who_started_script/(如果以root身份运行)。

更新3

使用${SLURM_SUBMIT_DIR}的方法仅在以下情况下有效:

cd /storage/software_folder/software_name
sbatch ./scripts/this_script.sh

但这似乎不是一个适当的解决方案。还有其他方法吗?

解决方案

#!/bin/bash
#SBATCH --nodes=1
#SBATCH --partition=my_partition_name
# 检查脚本是通过SLURM还是bash启动的
# 如果通过SLURM启动:变量'$SLURM_JOB_ID'将存在
# `if [ -n $SLURM_JOB_ID ]`检查$SLURM_JOB_ID是否不为空字符串
if [ -n $SLURM_JOB_ID ];  then
    # 通过scontrol和$SLURM_JOB_ID检查原始位置
    SCRIPT_PATH=$(scontrol show job $SLURM_JOBID | awk -F= '/Command=/{print $2}')
else
    # 否则:通过bash启动。获取真正的位置。
    SCRIPT_PATH=$(realpath $0)
fi
# 获取software_name的位置 
SHARED_PATH=$(dirname $(dirname $(SCRIPT_PATH)))
# 从路径中分离出software_name
SOFTWARE_NAME=$(basename $SHARED_PATH)
# 要复制项目的目标位置
LOCAL_SOFTWARE_FOLDER='/node_folder'
# 目标的修正路径
LOCAL_PATH=$LOCAL_SOFTWARE_FOLDER/$SOFTWARE_NAME
# 从网络存储复制软件文件夹到本地
cp -r $SHARED_PATH $LOCAL_SOFTWARE_FOLDER
# 运行脚本
sh $LOCAL_PATH/scripts/launch.sh

0