用shell脚本结合slurm功能实现批量任务并行提交

完成shell脚本根据输入自动生成0-n数字命名文件夹,文件夹包含输出文件夹路径的shell脚本。编写slurm脚本,调用shell脚本,实现批量提交,输出自动生成文件夹绝对路径

  • 这篇博客: slurm作业调度系统与天河二号的基本命令(新手入门, 以gs和vasp为例)中的   2.1 shell脚本文件与批处理文件的提交 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 用sbatch提交作业首先要申请资源,申请多少资源(节点数,输入输出等等)需要进行说明,有两种说明方法(以提交的shell脚本为task.sh为例,提交前建议给该文件777权限):
    个人目前使用情况(未在shell脚本中说明, 使用1个节点32个核,gjf计算文件/vasp计算文件夹内执行):
    (gaussian 16 : sbatch -c32 -pTH_LONG3N g16.sh)
    (VASP : sbatch -N 1 -n 32 -p TH_LONG3N vasp.sh)

    (1) 不在脚本中声明,在在终端中进行声明,如:
    ①shell脚本的内容如下:

    #!/bin/bash
    
    #<1.source 环境变量>
    # 天河二号和非sbatch提交的脚本会自动source ~/.bashrc,因此此步可以忽略
    # 本地计算机使用sbatch命令提交shell脚本,由于是在由于是在nonloginshell环境里运行,而非interactive loginshell,并不会自动source ~/.bashrc 的环境变量,因此有两种解决方案
    解决方案1: 此处加上source ~/.bashrc
    解决方案2: 此处按顺序export 和source所有所需的变量。
    
    # <2.执行运行软件>
    # 高斯执行方式1(gjf文件同目录下直接执行): g16 < test.gjf > test.out
    # 高斯执行方式2(同目录下,srun): srun -c 32 -p TH_LONG3N g16 < test.gjf > test.out
    # VASP执行方式1(文件夹内, srun,老超算): srun -p TH_NEW1 -N 1 -n 12 vasp软件路径
    # VASP执行方式2(文件夹内, srun,新超算): srun -p LONG_3N -N 1 -n 32 vasp软件路径
    

    ②终端提交命令如下:

    cd task.sh的文件路径 #mobaxterm可以中键锁定路径,不用手动输入了
    sbatch -p TH_LONG3N -N 1 -n 1 -c 32 task.sh #也可以winscp打开文件所在位置,shift+ctrl+T, 然后输入命令。这样可以不需要cd命令。
    

    (2) 在shell脚本文件开头进行声明,在终端直接提交:
    注释行并非没用, 第一行#!是说明用什么语言,比如bash语言,删了就不能正常运行。
    #SBATCH其实是能正常读取的。具体说明见北大超算sbatch 常用参数。2

    #!/bin/bash
    #SBATCH -p TH_LONG3N      	#可以用sinfo查看分区,老超算为TH_NEW1,新超算为TH_LONG3N,超算中debug3N分区不用参与大循环,但是运行时间上线为半小时。
    #SBATCH -N 1      			#使用1个节点
    #SBATCH -n 1      			#1个进程
    #SBATCH -c 32      			#每个任务所需要的核心数为32个核(clusters)。老超算则为12个核
    
    
    #<1.source 环境变量>
    # 天河二号和非sbatch提交的脚本会自动source ~/.bashrc,因此此步可以忽略
    # 本地计算机使用sbatch命令提交shell脚本,由于是在由于是在nonloginshell环境里运行,而非interactive loginshell,并不会自动source ~/.bashrc 的环境变量,因此有两种解决方案
    解决方案1: 此处加上 source ~/.bashrc
    解决方案2: 此处按顺序 exportsource 所有所需的变量。
    
    # <2.执行运行软件>
    # 高斯执行方式1(gjf文件同目录下直接执行): g16 < test.gjf > test.out
    # 高斯执行方式2(同目录下,srun): srun -c 32 -p TH_LONG3N g16 < test.gjf > test.out
    # VASP执行方式1(文件夹内, srun,老超算): srun -p TH_NEW1 -N 1 -n 12 vasp软件路径
    # VASP执行方式2(文件夹内, srun,新超算): srun -p LONG_3N -N 1 -n 32 vasp软件路径
    

    ②终端提交命令如下:

    cd task.sh的文件路径 #mobaxterm可以中键锁定路径,不用手动输入了
    sbatch task.sh #因为已经在sh文件中声明了,所以此处就不需要-N -n了
    

    补充: 如果想要多个程序并行执行,需要在程序运行命令后面加上&符号(运行该命令后继续执行脚本,而等待程序运行完再进入下一步),并且再sh脚本最后加上wait命令,即等待所有程序运行结束后脚本才停止。否则会因脚本的直接停止关掉程序。

你参考下,是不是你想要的


#!/bin/bash

# 获取输入参数
n=$1

# 创建目录
mkdir -p "$n"

# 生成脚本文件
cat <<EOF > "$n/output.sh"
#!/bin/bash

# 输出当前目录路径
echo "\$(pwd)"
EOF

# 授予脚本执行权限
chmod +x "$n/output.sh"

# 提交脚本到Slurm集群
sbatch "$n/output.sh"
#!/bin/bash

# 获取输入参数
n=$1

# 循环提交作业
for i in {0..n}
do
  # 创建目录
  mkdir -p "$i"

  # 生成脚本文件
  cat <<EOF > "$i/output.sh"
#!/bin/bash

# 输出当前目录路径
echo "\$(pwd)"
EOF

  # 授予脚本执行权限
  chmod +x "$i/output.sh"

  # 提交脚本到Slurm集群
  sbatch "$i/output.sh"
done

Linux相关操作_linux批量提交任务
可以参考下

先编写一个 shell 脚本,根据输入生成 0-n 数字命名的文件夹,并包含输出文件夹路径:


#!/bin/bash  
  
# 获取输入的数字范围  
min=$1  
max=$2  
  
# 创建输出文件夹路径  
output_dir="$PWD/output"  
if [ ! -d "$output_dir" ]; then  
    mkdir "$output_dir"  
fi  
  
# 循环创建文件夹  
for i in $(seq "$min" "$max"); do  
    folder_name="folder$i"  
    folder_path="$output_dir/$folder_name"  
    if [ ! -d "$folder_path" ]; then  
        mkdir "$folder_path"  
    fi  
done  
  
# 输出生成的文件夹绝对路径  
output_folders=("$output_dir/folder$min" "$output_dir/folder$((min+1))" "$output_dir/folder$max")  
for folder in "${output_folders[@]}"; do  
    echo "$folder"  
done

之后再编写一个 slurm 脚本,调用 create_folders.sh 脚本并批量提交


#!/bin/bash  
  
input_number=$1  
output_folder=$2  
  
for i in {0..$input_number}  
do  
    folder_name=$i  
    mkdir $folder_name  
    echo "output_folder=\"$output_folder/$folder_name/\"" > $folder_name/script.sh  
done








#!/bin/bash  
  
input_number=$1  
output_folder=$2  
  
for i in {0..$input_number}  
do  
    folder_name=$i  
    job_script=$folder_name/script.sh  
    output_folder=$output_folder/$folder_name/  
  
    sbatch << EOF  
    #!/bin/bash -l  
  
    #SBATCH --job-name=job-$folder_name  
    #SBATCH --output=job-%j.out  
    #SBATCH --error=job-%j.err  
    #SBATCH --ntasks=1  
    #SBATCH --mem-per-cpu=1000  
  
    bash $job_script  
  
    EOF  
done

参考如下:

#!/bin/bash

# 获取输入参数
n=$1

# 创建输出文件夹
for ((i=0; i<=n; i++))
do
    folder_name="folder_$i"
    mkdir $folder_name
    
    # 创建包含输出文件夹路径的shell脚本
    echo "#!/bin/bash" > $folder_name/output_script.sh
    echo "output_folder=\$(cd \$(dirname \$0); pwd)" >> $folder_name/output_script.sh
    
    chmod +x $folder_name/output_script.sh
done

保存以上脚本为generate_folders.sh

编写一个slurm脚本,调用上述shell脚本并实现批量提交任务。假设我们要生成10个文件夹,可以使用以下示例:

#!/bin/bash

#SBATCH --job-name=generate_folders
#SBATCH --output=generate_folders_%j.out
#SBATCH --error=generate_folders_%j.err

# 调用shell脚本生成文件夹和输出脚本
srun bash generate_folders.sh 10

# 输出自动生成的文件夹绝对路径
for ((i=0; i<=10; i++))
do
    folder_name="folder_$i"
    output_folder=$(cat $folder_name/output_script.sh | grep "output_folder" | awk -F'=' '{print $2}')
    
    echo "Folder $i: $output_folder"
done

保存以上脚本为submit_slurm.sh

最后,在终端中使用以下命令提交slurm任务:

sbatch submit_slurm.sh

shell脚本:

#!/bin/bash

n=$1

for ((i=0; i<=n; i++))
do
    folder_name="folder_$i"
    mkdir $folder_name

    # 创建输出路径的脚本文件
    echo "#!/bin/bash" > $folder_name/run.sh
    echo "echo \"当前文件夹的绝对路径:\$(pwd)\"" >> $folder_name/run.sh
done

效果:

img


slurm脚本:

#!/bin/bash
#SBATCH --job-name=generate_folders
#SBATCH --output=generate_folders_%j.out
#SBATCH --error=generate_folders_%j.err
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=1
#SBATCH --time=00:01:00

# 调用shell脚本生成文件夹和脚本文件,假设n=5
./script.sh 5

shell脚本示例

#!/bin/bash

echo "请输入一个整数 n:"
read n

for ((i=0; i<=n; i++))
do
    folder_name="folder_$i"
    mkdir $folder_name

    echo "#!/bin/bash" > ${folder_name}/output.sh
    echo "echo '输出文件夹路径: $(pwd)/$folder_name'" >> ${folder_name}/output.sh

    chmod +x ${folder_name}/output.sh
done