NWPC业务系统笔记:检查单个时次是否运行完成
目录
数值预报业务系统每天会执行多个循环,例如 GRAPES 全球预报系统每天计算 00、06、12 和 18 共四个时次的预报。 在每天运行的最后,会有一个任务用于清理几天前运行所占用的空间。 整个系统的结构,如下图所示。
ecFlow 只有在某个 suite 所有任务都运行完成才会自动滚动到下一天。 如果哪个任务没有正常完成,系统就会卡在这一天,影响后续任务的执行。 最近一段时间,因为任务运行超时被 slurm 杀掉,但任务没有被 aborted,导致任务一直处于 active 状态,容易被值班人员忽略。
目前还没有找到具体的原因。 推测可能是在系统出错时调用 ecflow_client 命令耗时较长,超过被 slurm 杀掉的作业允许的执行时间,导致 ecflow 服务没有接收到 aborted 信号。
当前的系统设计无法处理这种情况。 本文介绍一种检查单个时次是否运行完成的方法,为值班人员提供明确的提示信息。
原理
业务系统在设定 housekeeping 任务启动时间时,假定该时间点当天所有的时次已经完成。 所以,可以设置一组与 housekeeping 同时启动的任务,分别检查各个时次是否完成。 如下图所示:
实现
ecFlow 提供 complete 触发器,用于在符合条件的情况下跳过某个任务,但 complete 只支持 event 事件,不支持节点。 所以需要在脚本中手动检测任务是否完成。
ecFlow_client 命令无法直接获取某个节点的运行状态。 下面的代码使用 Python API 接口返回指定节点的运行状态字符串。
from __future__ import print_function
import argparse
import os
import ecflow
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--host", help="ecflow host")
parser.add_argument("--port", help="ecflow port")
parser.add_argument("--node-path", help="node path")
args = parser.parse_args()
client = ecflow.Client(args.host, args.port)
client.sync_local()
defs = client.get_defs()
node = defs.find_abs_node(args.node_path)
if node is None:
print("unknown")
return
status = str(node.get_dstate())
print(status)
if __name__ == "__main__":
main()
使用下面的命令获取节点状态:
python get_node_status.py \
--host=login_b01 \
--port=31071 \
--node-path=/meso_post/09
如果节点正常结束,命令返回 complete
。所以脚本中检查返回值是否为 complete
就可以。
status=$(python ${script_path} \
--host=${ECF_HOST} --port=${ECF_PORT} \
--node-path=/meso_post/${HH})
if [ "x${status}" != "xcomplete" ]; then
echo "============WARNING==============="
echo "/meso_post/${HH} is not complete!"
echo "============WARNING==============="
this_is_an_error
fi