等待一组qsub作业完成



我有一个批处理脚本,它启动了几个qsub作业,我想在它们全部完成时捕获它们。

我不想使用-sync选项,因为我希望它们同时运行。每个作业都有一组不同的命令行参数。

我希望我的脚本等到所有的工作都完成了,然后再做一些事情。我不想使用睡眠功能,例如检查是否在每30秒后生成了某些文件,因为这会消耗资源。

我相信Torque可能有一些选择,但我正在运行SGE。

关于如何实现这个,有什么想法吗?

谢谢P.s。我确实找到了另一条线索链接

其具有应答

您可以使用wait停止执行,直到完成所有作业。如果您循环等待特定的ID,您甚至可以收集所有退出状态和其他运行统计信息(所花费的时间、当时完成的作业数等)

但我不知道如何在不轮询某些值的情况下使用它。可以使用bash陷阱,但我如何使用qsub?

启动您的qsub作业,使用-N选项为它们提供任意名称(job1、job2等):

qsub -N job1 -cwd ./job1_script
qsub -N job2 -cwd ./job2_script
qsub -N job3 -cwd ./job3_script

启动您的脚本,并告诉它等待名为job1、job2和job3的作业完成后再启动:

qsub -hold_jid job1,job2,job3 -cwd ./results_script

如果所有作业的名称中都有一个通用模式,那么您可以在提交作业时提供该模式。https://linux.die.net/man/1/sge_types向您展示可以使用的模式。示例:

-hold_jid "job_name_pattern*"

另一种选择(从这里开始)如下:

FIRST=$(qsub job1.pbs)
echo $FIRST
SECOND=$(qsub -W depend=afterany:$FIRST job2.pbs)
echo $SECOND
THIRD=$(qsub -W depend=afterany:$SECOND job3.pbs)
echo $THIRD

深入了解到,qsub返回jobid,这通常被转储到标准输出中。相反,将其捕获在变量($FIRST$SECOND$THIRD)中,并在将作业排入队列时使用-W depend=afterany:[JOBIDs]标志来控制它们何时出队的依赖关系结构。

qsub -hold_jid job1,job2,job3 -cwd ./myscript

这在bash中有效,但思想应该是可移植的。使用-terse可以方便地建立一个具有要等待的作业ID的字符串;然后提交一个使用-hold_jid等待先前作业和-sync y的伪作业,以便qsub在它(以及所有预条件)完成之前不会返回:

# example where each of three jobs just sleeps for some time:
job_ids=$(qsub -terse -b y sleep 10)
job_ids=job_ids,$(qsub -terse -b y sleep 20)
job_ids=job_ids,$(qsub -terse -b y sleep 30)
qsub -hold_jid ${job_ids} -sync y -b y echo "DONE"  
  • -terse选项使qsub的输出仅为作业id
  • -hold_jid选项(如其他答案中所述)使作业等待指定的作业ID
  • -sync y选项(由OP引用)要求qsub在提交的作业完成之前不要返回
  • -b y指定该命令不是脚本文件的路径(例如,我使用sleep 30作为命令)

有关更多详细信息,请参阅手册页。

#!/depot/Python-2.4.2/bin/python
import os
import subprocess
import shlex
def trackJobs(jobs, waittime=4):
    while len(jobs) != 0:
        for jobid in jobs:
            x = subprocess.Popen(['qstat', '-j', jobid], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            std_out, std_err = x.communicate()
            if std_err :
                jobs.remove(jobid)
                break
        os.system("sleep " + str(waittime))
    return

这是一个简单的代码,您可以在其中跟踪qsub作业的完成情况。这里的函数接受jobId列表(例如['84210770','84210774','8.42100776','84.2100777','842100778'])

如果您有150个文件需要处理,并且每次只能运行15个,而其他文件都在队列中,则可以设置类似的内容。

# split my list files in a junk of small list having 10 file each
awk 'NR%10==1 {x="F"++i;}{ print >  "list_part"x".txt" }'  list.txt

以这样一种方式qsub所有作业,即每个list_part*.txt的第一个包含第二个。。。。第二个拿着第三个。。。。。等等

for list in $( ls list_part*.txt ) ; do
    PREV_JOB=$(qsub start.sh) # create a dummy script start.sh just for starting
 for file in  $(cat $list )  ; do
   NEXT_JOB=$(qsub -v file=$file  -W depend=afterany:$PREV_JOB  myscript.sh )
   PREV_JOB=$NEXT_JOB
 done
done

如果您在myscript.sh中有一个过程,需要移动或下载许多文件,或者在集群lan 中创建密集的流量,这将非常有用

您可以启动一个作业数组qsub -N jobname -t 1-"$numofjobs" -tc 20,然后它只有一个作业id,一次运行20个。您给它一个名称,然后一直保持,直到使用qsub -hold_jid jidqsub -hold_jid jobname完成该数组。

我需要更多的灵活性,所以我在这里为这个和其他目的构建了一个Python模块。您可以直接将模块作为演示的脚本(python qsub.py)运行。

用法:

$ git clone https://github.com/stevekm/util.git
$ cd util
$ python
Python 2.7.3 (default, Mar 29 2013, 16:50:34)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import qsub
>>> job = qsub.submit(command = 'echo foo; sleep 60', print_verbose = True)
qsub command is:
qsub -j y -N "python" -o :"/home/util/" -e :"/home/util/" <<E0F
set -x
echo foo; sleep 60
set +x
E0F
>>> qsub.monitor_jobs(jobs = [job], print_verbose = True)
Monitoring jobs for completion. Number of jobs in queue: 1
Number of jobs in queue: 0
No jobs remaining in the job queue
([Job(id = 4112505, name = python, log_dir = None)], [])

使用Python 2.7和SGE设计,因为我们的系统就是这样运行的。唯一需要的非标准Python库是包含的tools.pylog.py模块,以及sh.py(也包含)

如果您希望纯粹停留在bash中,显然没有那么大帮助,但如果您需要等待qsub作业,那么我可以想象您的工作流程正逐渐变得复杂,而使用Python会带来好处。

最新更新