监测云服务器机器人自动运行情况

问题

今天在查看云端录像的时候发现因为一些无法预料的异常导致机器人执行失败:
监测云服务器机器人自动运行情况

所以决定另外开发一个机器人来监测这个机器人的执行情况,如果执行失败则发邮件通知业务部门。

通过观察得知每次机器人运行完都会在文件夹 logs 中生成对应的日志,日志所在的文件夹以当前日期命名,且日志名称为 40 位长度的随机字符串。
监测云服务器机器人自动运行情况
监测云服务器机器人自动运行情况

打开日志,可以发现最后两行分别记录了机器人执行结果以及结果的详细信息:
监测云服务器机器人自动运行情况
监测云服务器机器人自动运行情况

那么只要打开这个文件然后检测末尾的一段字符串,看其中是否含有“失败”或者“成功”的文本就可以了。

思路

首先根据当前日期获得日志文件所在目录:

import time

path = 'C:/ueba/logs/' + str(time.localtime().tm_year) + '-' + '{:02d}'.format(time.localtime().tm_mon) + '-' + '{:02d}'.format(time.localtime().tm_mday)  # 月份和天数需要补齐两位

然后搜索路径中名称长度为 40 位的文件,在实际操作中发现如果当前服务器同一天有多个机器人运行,会在当前文件夹中生成多个名称长度为 40 位的文件,因此需要根据文件的创建时间来判断,我需要监测的云服务器机器人运行时间为上午七点,这部分代码如下:

import os

for i in os.listdir(path):
    if len(i) == 40 and time.strftime('%H:%M:%S', time.localtime(os.stat(path + '/' + i).st_ctime)) == '07:00:00':  # 名字长度为40且创建时间为七点
        path2 = path + '/' + i

正常情况下按行读取文件,然后获得最后两行就行了。但是有些机器人运行日志很大,一次性读取很可能会把内存撑爆,按行读取又很慢。所以先把指针移动到末尾前的一段位置,然后再读取:

if len(path2) > 60:  # 防止文件夹中没有日志文件
    try:        
        with open(path2, 'rb') as f:
            f.seek(-1000, 2)  # 指针移动至距离末尾1000个字节的位置
            lines = f.read().decode('ansi').strip().split('\n')[-1]  # txt文本默认存储格式为ANSI,需要按次格式解码,否则会报错
    except:
        pass

完整代码如下:

import os
import time
import ubpa.ioutlook as ioutlook
import ubpa.ibox as ibox

path = 'C:/ueba/logs/' + str(time.localtime().tm_year) + '-' + '{:02d}'.format(time.localtime().tm_mon) + '-' + '{:02d}'.format(time.localtime().tm_mday)

for i in os.listdir(path):
    if len(i) == 40 and time.strftime('%H:%M:%S', time.localtime(os.stat(path + '/' + i).st_ctime)) == '07:00:00':  # 名字长度为40且创建时间为七点
        path2 = path + '/' + i

print('文件路径:', path2)
lines = ''
if len(path2) > 60:
    try:        
        with open(path2, 'rb') as f:
            f.seek(-1000, 2)
            lines = f.read().decode('ansi').strip().split('\n')[-1]
    except:
        pass

if lines:
    if '失败' in lines:
        ioutlook.send_outlook(receiver='gxvdirpa4.ssc',subject='机器人执行异常',body='错误信息为:\n\n' + lines)
        ibox.msg_box(msg='邮件发送成功')
    elif '成功' in lines:
        ibox.msg_box(msg='机器人执行正常')

然后部署至云端,开始时间设置为需要监测的云服务器机器人运行完毕之后的时间段即可。
实际部署过程中发现不能在代码中加入print(lines),否则在运行完会提示任务执行失败。