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

Ara*_*390 8 variables bash path 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
Run Code Online (Sandbox Code Playgroud)

它运行完美,当我通过以下方式在节点本身上运行它(不使用 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/使用 SLURM 启动脚本时,是否可以在脚本内部 )?

PS 所有机器都运行 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
Run Code Online (Sandbox Code Playgroud)

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

解决方案

#!/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
Run Code Online (Sandbox Code Playgroud)

dam*_*ois 6

您可以通过以下方式获取提交脚本的初始(即提交时)位置scontrol

scontrol show job $SLURM_JOBID | awk -F= '/Command=/{print $2}'
Run Code Online (Sandbox Code Playgroud)

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

if [ -n $SLURM_JOB_ID ] ; then
THEPATH=$(scontrol show job $SLURM_JOBID | awk -F= '/Command=/{print $2}')
else
THEPATH=$(realpath $0)
fi
Run Code Online (Sandbox Code Playgroud)

然后继续

SHARED_PATH=$(dirname $(dirname "${THEPATH}"))
Run Code Online (Sandbox Code Playgroud)