批处理作业的分配时间可以在sbatch命令上指定以进行制止。例如,以下请求1天3分10秒:
$ sbatch -t 1-0:3:10 test.sh
我的脚本需要知道它将运行多长时间,以便它可以在终止之前保存所有数据。 sbatch手册页上列出的可用于作业的环境变量不包括分配时间限制。
如何从脚本中确定这一点?
现在,我要向队列管理器询问当前作业的时间限制:
#!/bin/sh
squeue -j $SLURM_JOB_ID -o "%l"
给出
TIME_LIMIT
1-00:04:00
我使用以下内容解析输出:
#!/bin/bash
TIMELIMIT=`squeue -j $SLURM_JOB_ID -o "%l" | tail -1`
echo Time limit $TIMELIMIT
if [[ $TIMELIMIT == *-* ]]; then
IFS='-' read -ra DAYS_HOURS <<< $TIMELIMIT
DAYS=${DAYS_HOURS[0]}
PART_DAYS=${DAYS_HOURS[1]}
else
DAYS=0
PART_DAYS=$TIMELIMIT
fi
if [[ $HOURS == *:*:* ]]; then
IFS=':' read -ra HMS <<< $PART_DAYS
H=${HMS[0]}
M=${HMS[1]}
S=${HMS[2]}
else
IFS=':' read -ra HMS <<< $PART_DAYS
H=0
M=${HMS[0]}
S=${HMS[1]}
fi
SECONDS=`echo "((($DAYS*24+$H)*60+$M)*60+$S)" | bc`
echo Time limit: $SECONDS seconds
HOURS=`echo "scale=3;((($DAYS*24+$H)*60+$M)*60+$S)/3600." | bc`
echo Time limit: $HOURS hours
给出
Time limit 1-00:04:00
Time limit: 86404 seconds
Time limit: 24.001 hours
是否有一种更清洁的方法?
答案 0 :(得分:1)
几件事。
如果使用proctrack / cgroup,则可以捕获在时间限制到期时发送的SIGTERM信号。这为您提供了可配置的时间来保存状态。 SIGKILL在KillWait秒后发送,在slurm.conf中配置。但是,如果您使用的是proctrack / linuxproc,则很难实现此目的,因为它会将SIGTERM发送到所有进程,而不仅仅是bash脚本。像这样:
#!/bin/bash
function sigterm {
echo "SIGTERM"
#save state
}
trap sigterm TERM
srun work.sh &
# This loop only breaks when all subprocesses exit
until wait; do :; done
如果您以前从未在bash中捕获信号,可能很难做到。通过proctrack / cgroup,SIGTERM被发送到每个作业步骤和批处理脚本的主进程。因此,在上面,work.sh还必须捕获SIGTERM。同样在上面,bash直到子进程结束后才会捕获信号,除非您将它们作为背景。因此是“&”并等待循环。
如果您确实想将时间限制传递到作业中,则可以使用环境变量。
sbatch --export=ALL,TIMELIMIT=1-0:3:10 -t1-0:3:10 test.sh
令人讨厌的是,您必须指定两次时间限制。
用squeue
查询控制器不是一个糟糕的解决方案。但是,大规模地,查询控制器的数千个作业可能会影响性能。请注意,您可以使用--noheader
标志来不每次都打印TIME_LIMIT,而不是使用tail
。
基本上,这是KillWait的设计目的,因此,除非出于某种原因不能使用,否则应考虑使用它。 https://slurm.schedmd.com/slurm.conf.html
最好的答案可能是对--signal
使用sbatch
选项。这样,您就可以在时限结束之前的一定时间内向您的工作发送可配置的信号。
sbatch --signal=B:USR1@120 myscript.sh
以上示例在作业结束前约2分钟将USR1发送到批处理脚本。如手册页中所述,分辨率为60秒,因此信号可以提前60秒发送。