如何获取用于 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
# getting location of software_name 
SHARED_PATH=$(dirname $(dirname $(realpath $0)))
# separating the software_name from path
SOFTWARE_NAME=$(basename $SHARED_PATH)
# target location to copy project
LOCAL_SOFTWARE_FOLDER='/node_folder'
# corrected path for target
LOCAL_PATH=$LOCAL_SOFTWARE_FOLDER/$SOFTWARE_NAME
# Copying software folder from network storage to local
cp -r $SHARED_PATH $LOCAL_SOFTWARE_FOLDER
# running the script
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而搞砸了所有内容

当使用SLURM启动脚本时,是否可以在脚本内部获取原始位置(/storage/software_folder/software_name/)?

附言所有机器都运行 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.它尝试运行,但是:

  • 在这种情况下,它仅使用指定的文件夹来创建输出文件
  • 软件仍然不想运行
  • 尝试在脚本打印/home/username_who_started_script内部使用echo "${SLURM_SUBMIT_DIR}"而不是/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
# check if script is started via SLURM or bash
# if with SLURM: there variable '$SLURM_JOB_ID' will exist
# `if [ -n $SLURM_JOB_ID ]` checks if $SLURM_JOB_ID is not an empty string
if [ -n $SLURM_JOB_ID ];  then
# check the original location through scontrol and $SLURM_JOB_ID
SCRIPT_PATH=$(scontrol show job $SLURM_JOBID | awk -F= '/Command=/{print $2}')
else
# otherwise: started with bash. Get the real location.
SCRIPT_PATH=$(realpath $0)
fi
# getting location of software_name 
SHARED_PATH=$(dirname $(dirname $(SCRIPT_PATH)))
# separating the software_name from path
SOFTWARE_NAME=$(basename $SHARED_PATH)
# target location to copy project
LOCAL_SOFTWARE_FOLDER='/node_folder'
# corrected path for target
LOCAL_PATH=$LOCAL_SOFTWARE_FOLDER/$SOFTWARE_NAME
# Copying software folder from network storage to local
cp -r $SHARED_PATH $LOCAL_SOFTWARE_FOLDER
# running the script
sh $LOCAL_PATH/scripts/launch.sh

您可以从scontrol获取提交脚本的初始(即在提交时)位置,如下所示:

scontrol show job "$SLURM_JOB_ID" | awk -F= '/Command=/{print $2}'

因此,您可以将realpath $0部分替换为上述部分。当然,这只能在 Slurm 分配中起作用。因此,如果您希望脚本在任何情况下都能正常工作,则需要一些逻辑,例如:

if [ -n "${SLURM_JOB_ID:-}" ] ; then
THEPATH=$(scontrol show job "$SLURM_JOB_ID" | awk -F= '/Command=/{print $2}')
else
THEPATH=$(realpath "$0")
fi

然后继续

SHARED_PATH=$(dirname "$(dirname "${THEPATH}")")

我必须在数组作业中做同样的事情,@damienfrancois接受的答案适用于所有作业,除了与 ArrayJobID 相同的 jobid。只需将 awk 命令管道到头部命令就可以解决问题

scontrol show job $SLURM_JOBID | awk -F= '/Command=/{print $2}' | head -n 1

在脚本中,获取SHARED_PATHSHARED_PATH="${SLURM_SUBMIT_DIR}"

将脚本提交为sbatch -D /storage/software ./scripts/this_script.sh

看这里。

从引用页面:

-D

将批处理脚本的工作目录设置为其前面的目录 被执行。路径可以指定为完整路径或相对路径 到执行命令的目录。

SLURM_SUBMIT_DIR

从中调用 sbatch 的目录,或者,如果适用,则由 -D, --chdir 选项指定的目录。

附言以上来自版本 19.05 doc.
在查看存档时,参考 Ver. 18.x(尤其是 18.08),它没有提到相同。看到这里

SLURM_SUBMIT_DIR.

从中调用批处理的目录。

相关内容

  • 没有找到相关文章

最新更新