如何获取用于 SLURM 作业的脚本的原始位置?
如何获取用于 SLURM 作业的脚本的原始位置?
我正在使用脚本启动SLURM作业,并且脚本必须根据其位置来工作,该位置在脚本本身中通过SCRIPT_LOCATION=$(realpath $0)
获得。但是SLURM会将脚本复制到slurmd
文件夹并从那里启动作业,这会搞乱后续操作。
在脚本被移动/复制之前,是否有任何选项可以获取用于slurm作业的脚本位置?
脚本位于网络共享文件夹/storage/software_folder/software_name/scripts/this_script.sh
,它必须执行以下操作:
- 获取自己的位置
- 返回
software_name
文件夹 - 将
software_name
文件夹复制到节点上的本地文件夹/node_folder
- 从复制的文件夹
/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