【问题标题】:How to know when PBS batch jobs are complete如何知道 PBS 批处理作业何时完成
【发布时间】:2014-09-04 20:14:03
【问题描述】:

我有一个 BASH 脚本,可以将多个串行作业提交到 PBS 排队系统。提交作业后,脚本结束。然后这些作业在集群上运行,当它们全部完成后,我可以继续下一步。典型的工作流程可能涉及其中几个步骤。

我的问题:

有没有办法让我的脚本在提交完成后不退出,而是休眠,直到该脚本提交的所有作业都在集群上完成,然后才退出?

【问题讨论】:

  • 到目前为止,在手动启动下一个脚本之前,我一直在等待步骤。我可以通过检查作业完成后转储的所有 job.o/job.e 文件的存在并计算它们来想出一种笨拙的方法。不过我还没试过。
  • 或许将wait 添加到脚本的末尾? (见man bashwait
  • @DavidC.Rankin:我不认为wait 是答案。这些是提交的批处理作业,而不是 shell 的子进程。
  • 您可以编写一个重复调用qsub 的脚本(最好有一些延迟,以免系统过载)并在所有指定作业完成后终止。这很丑陋,但它应该可以工作。如果没有人提出更好的解决方案,我可能会发布这个答案。
  • 我在考虑这个,基思。我想我更喜欢检查 job.o 文件数量的脚本。这样您就不需要知道作业提交编号,也不必一直调用 qsub 来检查那些作业是否不存在。您只需要知道您提交了多少作业,并且该数字等于已知目录中 .o 文件的数量。顺便说一句,我写了一些东西来检查 job.o 文件的数量。可以发吗?? -- 不太确定这里的礼仪(这是我的第一篇文章)

标签: bash pbs


【解决方案1】:

您正在尝试建立工作流程,对吗?完成您要完成的工作的最佳方法是使用job dependencies。本质上,您要做的是提交 X 个作业,然后提交更多依赖于第一组作业的作业,您可以使用作业依赖项来执行此操作。您可以在上一个链接中了解执行依赖项的不同方法,但这里有一个示例,提交 3 个作业,然后再提交 3 个作业,直到前 3 个作业退出后才会执行。

#first batch
jobid1=`qsub ...`
jobid2=`qsub ...`
jobid3=`qsub ...`

#next batch
depend_str="-W after:${jobid1} -W after:${jobid2} -W after:${jobid3}"
qsub ... $depend_str
qsub ... $depend_str
qsub ... $depend_str

【讨论】:

    【解决方案2】:

    一种方法是使用 GNU Parallel 命令“sem”

    我也了解到这种做队列的事情。它充当计时器,允许在退出等后执行命令。

    编辑:我知道这里的示例非常基础,但是使用并行 --sem 甚至一般来说并行运行任务可以实现很多目标。看看教程,我相信你会找到一个相关的例子来帮助你。

    There is a great tutorial here

    教程中的一个例子:

      sem 'sleep 1; echo The first finished' &&
        echo The first is now running in the background &&
        sem 'sleep 1; echo The second finished' &&
        echo The second is now running in the background
      sem --wait
    

    输出:

    第一个现在在后台运行

    第一个完成

    第二个现在在后台运行

    第二个完成

    See Man Page

    【讨论】:

      【解决方案3】:

      要实际检查作业是否完成,我们需要使用qstat 和作业ID 来获取作业状态,然后使用grep 获取状态代码的状态。只要您的用户名或工作名称不是“C”,以下应该可以工作:

      #!/bin/bash
      
      # SECTION 1: Launch all jobs and store their job IDs in a variable
      
      myJobs="job1.qsub job2.qsub job3.qsub" # Your job names here
      numJobs=$(echo "$myJobs" | wc -w)      # Count the jobs
      myJobIDs=""                            # Initialize an empty list of job IDs
      for job in $myJobs; do
          jobID_full=$(qsub $job)
          # jobID_full will look like "12345.machinename", so use sed
          # to get just the numbers
          jobID=$(echo "$jobID_full" | sed -e 's|\([0-9]*\).*|\1|')
          myJobIDs="$myJobIDs $jobID"        # Add this job ID to our list
      done
      
      # SECTION 2: Check the status of each job, and exit while loop only
      # if they are all complete
      
      numDone=0                              # Initialize so that loop starts
      while [ $numDone -lt $numJobs ]; do    # Less-than operator
          numDone=0                          # Zero since we will re-count each time
          for jobID in $myJobIDs; do         # Loop through each job ID
      
              # The following if-statement ONLY works if qstat won't return
              # the string ' C ' (a C surrounded by two spaces) in any
              # situation besides a completed job.  I.e. if your username
              # or jobname is 'C' then this won't work!
              # Could add a check for error (grep -q ' E ') too if desired
              if qstat $jobID | grep -q ' C ' 
              then
                  (( numDone++ ))
              else
                  echo $numDone jobs completed out of $numJobs
                  sleep 1
              fi
          done
      done
      
      echo all jobs complete
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-06-16
        • 1970-01-01
        • 2020-10-25
        • 1970-01-01
        • 2012-02-19
        • 1970-01-01
        • 2012-04-17
        相关资源
        最近更新 更多