NWPC业务系统笔记:检查单个时次是否运行完成

目录

数值预报业务系统每天会执行多个循环,例如GRAPES全球预报系统每天计算00时次、06时次、12时次和18时次共四个时次的预报。 在每天运行的最后,会有一个任务用于清理几天前运行所占用的空间。整个系统的机构,如下图所示。

GRAPES全球预报后处理系统的示意图,每天有四个时次,在第二天02:00 UTC会执行housekeep_final任务清理空间

ecFlow只有在某个suite所有任务都运行完成才会自动滚动到下一天。 如果哪个任务没有正常完成,系统就会卡在这一天,影响后续任务的执行。 最近一段时间,因为任务运行超时被slurm杀掉,但任务没有被aborted,导致任务一直处于active状态,容易被值班人员忽略。 目前还没有找到具体的原因,推测可能是在系统出错时调用ecflow_client命令耗时较长,超过被slurm杀掉的作业允许的执行时间,导致ecflow服务没有接收到aborted信号。

当前的系统设计无法处理这种情况,本文介绍一种检查单个时次是否运行完成的方法,为值班人员提供明确的提示信息。

原理

业务系统在设定housekeeping任务启动时间时,假定该时间点当天所有的时次已经完成。 所以,可以设置一组与housekeeping同时启动的任务,分别检查各个时次是否完成。 如下图所示:

GRAPES区域模式系统各个时次的检查任务

实现

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