SIT-LogFilter — 服务器 SIT 测试日志过滤工具使用说明书 ← 返回

SIT-LogFilter — 服务器 SIT 测试日志过滤工具使用说明书


1. 概述

SIT-LogFilter 是 Inventec TA Team 开发的服务器 SIT(System Integration Testing)日志过滤工具,版本 Rev: 1.4.17

核心功能

在服务器 SIT 测试过程中,自动完成以下任务:

  1. 测试前:清除系统日志(SEL/dmesg/messages/mcelog),确保测试结果不受历史日志干扰
  2. 测试中:配置并确保 mcelog 守护进程在后台运行
  3. 测试后:收集 PCI/SEL/SDR/dmesg/messages/mcelog 日志,以 error_key.json 为标准执行黑白名单过滤
  4. 输出:被黑名单命中的日志记录在 reports/errors.log

支持的客户项目

客户 状态
Baidu 支持
Ali 支持(含 MOC 1.5 AER 过滤)
Tencent 支持
JD 支持
ByteDance 支持

支持的操作系统

技术栈

本地下载📁 本地下载

提示:点击按钮将打开网络文件夹,点击即可下载

文件 适用系统 版本
SIT-LogFilter-v1.4.17.zip RHEL/CentOS 6/7/8, Debian 9/10 v1.4.17

2. 目录结构

SIT-LogFilter-v1.4.17/
├── README.md                          # 项目说明文档
├── hosts                              # Ansible 主机清单模板
├── .gitlab-ci.yml                     # GitLab CI/CD 流水线配置
├── .gitignore                         # Git 忽略规则
│
└── LogFilterTool/                     # 主工具目录
    ├── LogFilterTool.py               # ★ 主入口脚本
    ├── error_key.json                 # ★ 黑白名单数据库(619 行)
    ├── lib/                           # 库模块目录
    │   ├── FuncColors.py              # ANSI 终端颜色定义
    │   ├── FuncCheckVersion.py        # OS / Python 版本检测
    │   ├── FuncGetSelEntry.py         # IPMI SEL -vvv 详细条目解析
    │   ├── FuncHelpers.py             # 通用工具函数集
    │   ├── FuncMultiFilter.py         # 多进程黑白名单过滤引擎
    │   ├── FuncParsePci.py            # PCIe 设备寄存器检查
    │   ├── FuncParseSysLog.py         # Ali MOC 1.5 AER 日志解析
    │   ├── FuncProgressBar.py         # 进度条 + 线程进度条
    │   └── FuncRCservice.py           # rc-local 开机启动服务配置
    └── cache/                         # 缓存与模板目录
        ├── cache.json                 # error_key.json 的备份副本
        ├── keeps.json                 # 需要保留的日志文件列表
        ├── mcelog.service             # mcelog systemd 服务单元模板
        └── parsers.json               # 解析所需日志文件列表

3. SIT 测试工作流程

┌─────────────────────────────────────────────────────────┐
│                    SIT 测试完整流程                       │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  【阶段 1: 测试前 — Pre-Test】                           │
│                                                         │
│  ┌──────────────────────────────────────┐               │
│  │ $ python LogFilterTool.py --before   │               │
│  ├──────────────────────────────────────┤               │
│  │ 1. 检查 ipmitool 是否可用             │               │
│  │ 2. 清除旧 reports/ 日志               │               │
│  │ 3. 配置 rc-local 开机启动服务          │               │
│  │ 4. 执行各日志清除命令(prerequisite)   │               │
│  │    ├─ ipmitool sel clear (BMC SEL)   │               │
│  │    ├─ dmesg -c / dmesg -C (内核)     │               │
│  │    ├─ rm /var/log/messages*          │               │
│  │    └─ echo -n > /var/log/mcelog      │               │
│  │ 5. 配置 mcelog daemon 开机启动        │               │
│  │ 6. 保留关键日志(keeps.json)          │               │
│  └──────────────────────────────────────┘               │
│                         │                               │
│                         ▼                               │
│  【阶段 2: 测试中 — During Test】                        │
│                                                         │
│  ┌──────────────────────────────────────┐               │
│  │ AC PowerCycle / 压力测试 / 功能测试    │               │
│  │ mcelog daemon 持续记录硬件错误          │               │
│  └──────────────────────────────────────┘               │
│                         │                               │
│                         ▼                               │
│  【阶段 3: 测试后 — Post-Test】                          │
│                                                         │
│  ┌──────────────────────────────────────┐               │
│  │ $ python LogFilterTool.py --after    │               │
│  ├──────────────────────────────────────┤               │
│  │ 1. 配置 mcelog daemon               │               │
│  │ 2. 收集日志(artifacts)              │               │
│  │    ├─ ipmitool sel elist → sel.log   │               │
│  │    ├─ ipmitool sel elist -vvv        │               │
│  │    ├─ ipmitool sdr elist → sdr.log   │               │
│  │    ├─ dmesg → dmesg.log              │               │
│  │    ├─ zcat messages + cat messages   │               │
│  │    ├─ cat /var/log/mcelog → mcelog   │               │
│  │    └─ lspci -vvv → pci.log           │               │
│  │ 3. 多进程过滤解析(parser)            │               │
│  │    ├─ check_sel() — SEL 黑白名单      │               │
│  │    ├─ check_dmesg() — dmesg 过滤     │               │
│  │    ├─ check_msg() — messages 过滤    │               │
│  │    ├─ check_mce() — mcelog 过滤      │               │
│  │    ├─ check_moc() — MOC AER 过滤     │               │
│  │    └─ check_pci() — PCIe 异常检查    │               │
│  │ 4. 去重(uniq_error)                │               │
│  │ 5. 输出 errors.log                   │               │
│  └──────────────────────────────────────┘               │
│                                                         │
└─────────────────────────────────────────────────────────┘

离线解析模式

当 PowerCycle 多轮测试产生大量日志时,为避免解析占用 SUT 时间:

  1. 在 SUT 上仅收集不解析:python LogFilterTool.py --after --disable-parse
  2. 将整个脚本包拷贝到闲置机器
  3. 执行离线解析:python LogFilterTool.py --parse

4. 主入口 — LogFilterTool.py

文件位置:LogFilterTool/LogFilterTool.py

这是整个工具的入口脚本,包含 Diagnostic 类(12 个方法)、配置读取函数和 CLI 参数解析。

4.1 Diagnostic 类

class Diagnostic(object):

核心诊断类,封装所有日志清除、收集、过滤、检查逻辑。

__init__() — 初始化

config_mce() — 配置 mcelog 守护进程

  1. 检查 OS 版本是否为 6~9 系列(RHEL/CentOS/Debian)
  2. 检查 mcelog 进程是否已在 daemon 模式运行:ps -ef | grep -v grep | grep mcelog
  3. 若未运行,执行:/usr/sbin/mcelog --ignorenodev --daemon --syslog --logfile=/var/log/mcelog
  4. 将启动命令追加到 /etc/rc.local,确保开机自启
  5. 设置 rc.local 权限为 755

prerequisite(logs) — 测试前日志清除

artifacts(logs) — 测试后日志收集

check_sel() — SEL 日志检查

check_sdr(allows) — SDR 日志检查

check_dmesg() — dmesg 日志检查

  1. 先以 advance 模式过滤:检查 errors_ignoreerrors_fixed 列表
  2. 再以标准模式过滤:黑白名单匹配

check_msg() — messages 日志检查

check_mce() — mcelog 日志检查

check_moc() — MOC AER 日志检查

check_pci() — PCIe 设备检查

uniq_error() — 错误去重

check_error() — 最终错误报告

clear_log(scenario, keep) — 日志清理

parser() — 解析编排器

解析主流程,按顺序执行所有检查:

check_sel() → check_dmesg() → check_msg() → check_mce() → check_moc() → check_pci() → uniq_error() → check_error()

4.2 read_config()

模块级函数,负责加载配置。

4.3 args_parser()

模块级函数,CLI 参数定义(使用 argparse):

参数 类型 说明
--before flag 测试前清除系统日志
--after flag 测试后收集并过滤日志
--parse flag 仅过滤解析已有日志(离线模式)
--disable-parse flag 收集日志但跳过过滤解析
--moc flag 启用 Ali MOC 1.5 AER 过滤
--keyverify flag 仅验证 error_key.json 格式
-y / --assumeyes flag 自动回答 yes(跳过交互确认)
--no-recommends flag 不弹出建议提示

约束:--before--after 不能同时使用。

4.4 main()

模块级函数,主流程控制:

args_parser()           → 解析命令行参数
read_config()           → 加载 error_key.json
Diagnostic()            → 初始化
← --parse 模式直接进入 parser()
检查 ipmitool 可用性    → 不可用则退出
clear_log('before')     → 清除旧日志
rcService()             → 配置 rc-local 服务
├─ --before:
│    prerequisite()     → 清除系统日志
│    config_mce()       → 配置 mcelog
│    clear_log('after', keep=True)
└─ --after:
     config_mce()
     artifacts()        → 收集日志
     parser() if not --disable-parse
     clear_log('after', keep=True)

4.5 全局变量

LOGDIR  = './reports'            # 输出目录
BAKDIR  = './backups'            # 备份目录
ERRLOG  = './reports/errors.log' # 错误报告文件
KEYS    = [ 'AER:' ]             # MOC AER 过滤关键字
KEEP_LOG = fopen('./cache/keeps.json', json=True)   # 保留日志列表
KEEP_LOGS = dumps([...])         # 日志文件名(无扩展名)

5. 库模块 — lib/

5.1 FuncColors.py — ANSI 颜色代码

文件位置:LogFilterTool/lib/FuncColors.py

Colors

定义 ANSI 终端转义序列常量,支持 8 种颜色 x 5 种样式:

颜色 前景(FG) 亮色前景 下划线 背景(BG) 亮色背景
Black \033[30m \033[30;1m \033[30;4m \033[40m \033[40;1m
Red \033[31m \033[31;1m \033[31;4m \033[41m \033[41;1m
Green \033[32m ... ... ... ...
Yellow \033[33m ... ... ... ...
Blue \033[34m ... ... ... ...
Magenta \033[35m ... ... ... ...
Cyan \033[36m ... ... ... ...
White \033[37m ... ... ... ...
Reset \033[0m

命名规律fg<Color> 前景、fgBright<Color> 亮前景、fg<Color>Line 下划线、bg<Color> 背景、bgBright<Color> 亮背景。

LEVEL_COLOR_MAP

日志级别到带颜色标签的映射字典:

LEVEL_COLOR_MAP = {
    "debug"  : "DEBUG"   (bgBrightMagenta),
    "info"   : "INFO"    (bgBrightBlue),
    "success": "SUCCESS" (bgBrightGreen),
    "warning": "WARNING" (bgBrightYellow),
    "fail"   : "ERROR"   (bgBrightRed),
    "system" : "SYSTEM"  (bgBrightWhite)
}

5.2 FuncCheckVersion.py — 系统版本检测

文件位置:LogFilterTool/lib/FuncCheckVersion.py

getPython(part=0)

检测 Python 解释器版本:

getSystem(type='')

检测操作系统版本:

5.3 FuncGetSelEntry.py — SEL 条目解析

文件位置:LogFilterTool/lib/FuncGetSelEntry.py

SelEntry

解析 ipmitool sel elist -vvv 输出的详细 SEL 条目。

工作流程

  1. execute(commands, shell):通过 subprocess.Popen 执行命令,捕获 stdout 和 stderr
  2. parser(key)
  1. output(commands, shell):整合输出 —— 头部 + 条目头: 条目内容 拼接
  2. write(filename):将结果写入文件

调用链

LogFilterTool.artifacts() → ipmi_cmd 'sel_vlist: ipmitool sel elist -vvv'
  → SelEntry().output(cmd, shell=True)
  → reports/sel_vlist.log

5.4 FuncHelpers.py — 通用工具函数

文件位置:LogFilterTool/lib/FuncHelpers.py

catch_except_handle(func)

装饰器,捕获函数执行中的所有异常,红色打印错误信息,返回 False

fopen(file, content='', mode='r', json=False)

统一文件 I/O 函数,根据 mode 读写文件:

mode 行为
'r' 读取文件全部内容(json=True 时用 json.loads 解析)
'w' 覆盖写入(json=True 时先 json.dumps 序列化)
'a' 追加写入

diff_array(origin, latest)

比较两个列表的差异,返回 {"del": [...], "add": [...]}

readme_ver(file)

从 README.md 中通过 grep -Po 提取版本号(匹配 Rev: X.Y.Z 格式)。

whole_match(pattern, key)

白名单核心匹配算法。实现"关键词前后必须有空格"的规则:

def whole_match(pattern, key):
    start = pattern[0:len(key)] == key and pattern[len(key)] == ' '
    end   = pattern[-len(key):] == key and pattern[-(len(key)+1)] == ' '
    return ' {} '.format(key) in pattern or start or end

三种匹配方式:

  1. keyword 在句子中间(前后有空格)
  2. 句首:keyword (关键词在开头,紧随空格)
  3. 句尾: keyword(关键词在结尾,前面有空格)

del_ansi(text)

使用正则 \x1B(?:[@-Z\\-_]|\[[0-?][ -/][@-~]) 去除 ANSI 转义序列。

recursive_del_ansi(directory, extensions)

递归遍历目录,批量清除指定扩展名文件(默认 .log.txt)中的 ANSI 代码。

5.5 FuncMultiFilter.py — 多进程黑白名单过滤器

文件位置:LogFilterTool/lib/FuncMultiFilter.py

这是整个工具的核心过滤引擎。

MultiFilter

class MultiFilter(object):
    def __init__(self, data, file, log_type):
        self.data     = data        # 来自 error_key.json 的域配置
        self.file     = file        # 待过滤日志文件路径
        self.log_type = log_type    # 过滤模式: None/'mcelog'/'advance'
        self.denies   = data.get('black_ls')  # 黑名单
        self.allows   = data.get('white_ls')  # 白名单

__call__() — 多进程调度

  1. 使用 multiprocessing.Manager().dict() 创建共享字典收集结果
  2. 读取日志文件全部内容,去除非 ASCII 字符:sub('[^\x00-\x7f]', '', content)
  3. 按行拆分,每行启动一个独立 Process 执行过滤
  4. 根据 log_type 选择 worker 函数:
  1. 等待所有进程完成(job.join()),合并返回结果列表

worker(idx, line, return_dict) — 标准黑白名单过滤

def worker(self, idx, line, return_dict):
    items = []
    for deny in self.denies:
        count = 0
        for allow in self.allows:
            if whole_match(line, allow):
                count += 1
        if line not in items and count == 0:
            if deny.lower() in line.lower():
                items.append(line)
            elif search('Call Trace:', line, I):
                items.append(line)
    return_dict[idx] = items

过滤逻辑

  1. 遍历每个黑名单关键词(deny
  2. 检查该行是否被任一白名单whole_match)匹配 → count += 1
  3. count == 0(未被白名单豁免)且黑名单匹配(deny.lower() in line.lower()),则命中
  4. Call Trace: 特殊处理:直接命中(常伴随内核 panic/软锁等严重问题,用于追踪调用栈)

worker_mce(idx, line, return_dict) — mcelog 过滤

def worker_mce(self, idx, line, return_dict):
    items = []
    if line.strip():  # 非空行
        _ = [items.append(line) for e in self.allows
             if not whole_match(line, e)]
    return_dict[idx] = items

mcelog 没有黑名单,只有白名单:

worker_adv(idx, line, return_dict) — dmesg 高级过滤

def worker_adv(self, idx, line, return_dict):
    items = []
    x, y = self.data.get('errors_ignore'), self.data.get('errors_fixed')
    _ = [ items.append(line) for e in x if e.lower() in line.lower() ]
    _ = [ items.append(line) for e in y if e in line ]
    return_dict[idx] = items

用于 dmesg 的预过滤阶段(在标准黑白名单之前运行):

5.6 FuncParsePci.py — PCIe 设备检查器

文件位置:LogFilterTool/lib/FuncParsePci.py

PciParser

class PciParser(object):
    def __init__(self, logname='./errors.log', devices=[]):
        self.maps = {
            "step1": [ 'uesta', 'uemsk', 'cesta', 'cemsk' ],
            "step2": [ 'AdvNonFatalErr', 'NonFatalErr' ],
            "step3": [ 'UnSupReq' ]
        }

三步 PCIe 检查算法(由 pci_worker 实现):

每个 PCIe 设备会读取 4 个寄存器:UESta(不可恢复错误状态)、UEMsk(不可恢复错误掩码)、CESta(可恢复错误状态)、CEMsk(可恢复错误掩码)。

Step 1 — 状态/掩码比对

pair UESta ↔ UEMsk 和 CESta ↔ CEMsk
对于每对寄存器中的同一位:
  如果 Status 位 = '+'(错误发生)AND Mask 位 = '-'(未屏蔽)
    → 记录此位,进入 Step 2

Step 2 — 错误类型判定

如果 Step 1 检出的位是 AdvNonFatalErr 或 NonFatalErr:
  → 进入 Step 3(特殊处理)
否则:
  → 直接报出异常: [Lspci]: Bus ID: XX abnormal item YY

Step 3 — UnSupReq 检查

如果 UESta 中 UnSupReq 也为 '-(正常)':
  → 加报 UnSupReq 异常
否则:
  → 忽略(该 NonFatalErr 为预期行为)

多进程 PCIe 解析

pci_filter() 方法:

  1. 如果指定了 devices 参数,通过 lspci | grep -iE "device1|device2|..." 筛选目标设备
  2. 为每个 PCIe 设备启动独立进程执行 pci_worker()
  3. 使用 ProgressBar 显示解析进度

pci_log_handle()

解析完成后,若 errors.log 为空则删除文件(无异常时的清理)。

独立运行

FuncParsePci.py 可独立运行:

$ python FuncParsePci.py -l ./errors.log -d "NVIDIA,Mellanox"

参数:

5.7 FuncParseSysLog.py — MOC AER 日志过滤器

文件位置:LogFilterTool/lib/FuncParseSysLog.py

专为 Ali MOC 1.5 (25G) 测试设计,从 messages 日志中筛选 AER (Advanced Error Reporting) 相关信息。

SysLogParser

class SysLogParser(object):
    def __init__(self, keys):
        self.key_ls = keys      # 搜索关键字,如 ['AER:']
        self.regex  = r'^\w{3}\s{1,2}\d{1,2}\s(\d{2}:){2}\d{2}\s'

parseMocLog(keys) — 日志解析

  1. 遍历 /var/log/messages* 所有文件(包括轮转文件)
  2. 筛选所有带时间戳的行(匹配 Mon DD HH:MM:SS 格式)
  3. 从文件修改时间获取年份
  4. 对每个匹配关键字的行,计算:

getMocLog() — 按小时分组统计

                               ┌─ 发生次数 <= 5 → WARNING
每小时内的 AER 出现次数 ──┤
                               └─ 发生次数 > 5  → ERROR(附详细消息列表)

输出文件

文件 内容
reports/filter_messages.json 按 time_mark 分组的 JSON 数据
reports/moc_messages.log 人类可读报告,含 WARNING/ERROR 分类表

独立运行

$ python FuncParseSysLog.py AER: "PCIe Error"

5.8 FuncProgressBar.py — 进度条

文件位置:LogFilterTool/lib/FuncProgressBar.py

ProgressBar

可配置的终端进度条组件。

预定义格式

格式常量 效果
DEFAULT Progress: [████████░░░░] 75%
ON_DONE Complete: [████████████] 100%(完成后自动切换)
FULL ━━ 35/50 (70%) eta 0:00:15 → 当前操作描述
HEAD Processing wait 50 secs(头部提示)

关键参数

__call__() 方法:每次调用刷新进度条,计算百分比、填充宽度、剩余时间。

done() 方法:标记完成,current = total,打印完成状态。

ThreadBar

继承 threading.Thread,用于长时间运行任务的后台进度显示

class ThreadBar(Thread):
    def __init__(self, message='Waiting test done', wait=10, duty=60, fmt=FULL):
        self.pause  = Event()   # 暂停事件
        self.cancel = Event()   # 取消事件

在 LogFilterTool 中的使用

threadbar = ThreadBar('collecting logs', -1, 300)   # 持续模式,300秒超时
threadbar.start()
try:
    # 执行过滤...
    threadbar.stop()
except KeyboardInterrupt:
    threadbar.stop()

5.9 FuncRCservice.py — rc-local 服务配置

文件位置:LogFilterTool/lib/FuncRCservice.py

rcService() 函数

自动检测操作系统版本并配置 rc-local 开机启动服务,确保 mcelog daemon 在系统重启后能自动运行

支持的操作系统

OS 版本 process
RHEL/CentOS 6 创建 rc.localln -sf 软链接 → chmod 777
RHEL/CentOS 7 创建 rc-local.service systemd 单元 → 创建 rc.local → 启用服务
RHEL/CentOS 8 同上 + 关闭透明大页(transparent_hugepage=never
Debian 9/10 Debian 风格的 rc-local.service 配置

工作流程

检查 rc-local.service 状态
  │
  ├─ 已是 active 状态 → 跳过(打印绿色 * 标记)
  │
  └─ 非 active 状态:
      ├─ 创建 /etc/rc.d/ 目录
      ├─ 创建 /etc/rc.d/rc.local 文件(模板包含 touch /var/lock/subsys/local)
      ├─ 根据 OS 版本写入对应的 rc-local.service systemd 单元
      ├─ ln -sf /etc/rc.d/rc.local /etc/rc.local  (软链接)
      ├─ chmod 777 /etc/rc.d/rc.local
      ├─ systemctl enable rc-local
      └─ systemctl restart rc-local

配置模板差异


6. 配置文件 — error_key.json

文件位置:LogFilterTool/error_key.json

这是整个工具的核心配置数据库,定义了五大日志域的过滤规则(619 行)。

6.1 JSON 结构

{
    "bmc": {
        "black_ls": [ "fault", "disabled", "unr", ... ],    // 105 个黑名单
        "white_ls": [ "Transition to OK", ... ],              //   3 个白名单
        "clear_cmd": "ipmitool sel clear",
        "ipmi_cmd": [
            "sdr: ipmitool sdr elist",
            "sel: ipmitool sel elist",
            "sel_vlist: ipmitool sel elist -vvv"
        ],
        "name": "sellog"
    },
    "dmesg": {
        "black_ls":       [ ... ],   // 223 个黑名单
        "white_ls":       [ ... ],   // ~70 个白名单
        "errors_ignore":  [ ... ],   // 高级过滤 — 需忽略的软错误
        "errors_fixed":   [ ... ],   // 高级过滤 — 已修复的已知错误
        "clear_cmd": "dmesg -c 2> /dev/null; dmesg -C 2> /dev/null",
        "cmd": "dmesg",
        "name": "dmesg"
    },
    "messages": {
        "black_ls":  [ ... ],        // 202 个黑名单
        "white_ls":  [ ... ],        // ~95 个白名单
        "clear_cmd": "rm -f /var/log/Xorg.* ...; cat /dev/null > /var/log/messages",
        "cmd": "zcat /var/log/messages.*.gz 2> /dev/null; cat $(ls /var/log/messages* | grep -v .gz) ...",
        "name": "messages"
    },
    "mcelog": {
        "clear_cmd": "echo -n > /var/log/mcelog",
        "cmd": "cat /var/log/mcelog 2> /dev/null",
        "name": "mcelog",
        "white_ls": [ "mcelog server already" ]   // 仅有白名单,无黑名单
    },
    "pci": {
        "cmd": "lspci -vvv 2> /dev/null",
        "name": "pci",
        "white_ls": []
    }
}

各域字段说明

字段 用途 必填
black_ls 黑名单关键词列表 否(mcelog 无)
white_ls 白名单关键词列表 否(pci 无)
clear_cmd 测试前清除日志的 Shell 命令
cmd 测试后收集日志的 Shell 命令 是(pci/mcelog/dmesg/messages)
ipmi_cmd BMC 相关的 IPMI 命令(替代 cmd) 是(bmc)
name 日志文件命名标识
errors_ignore dmesg 高级过滤 — 忽略的软错误 否(仅 dmesg)
errors_fixed dmesg 高级过滤 — 已修复的已知错误 否(仅 dmesg)

6.2 黑白名单过滤算法

输入: 日志文件的每一行
┌─────────────────────────────────────────┐
│  遍历 black_ls 黑名单                      │
│    │                                      │
│    ├─ deny 匹配行内容 (大小写不敏感)         │
│    │    │                                  │
│    │    ├─ 检查 white_ls 白名单              │
│    │    │    │                              │
│    │    │    ├─ 任一 allow 命中 (whole_match) │
│    │    │    │  → 跳过 (白名单豁免)            │
│    │    │    │                              │
│    │    │    └─ 无 allow 命中                 │
│    │    │       → 标记为错误,写入 errors.log  │
│    │    │                                    │
│    │    └─ "Call Trace:" 特殊处理             │
│    │       → 直接标记(不检查白名单)           │
└─────────────────────────────────────────┘

关键规则(来自 README.md):

  1. 黑名单匹配:不分大小写,该行含指定单字则匹配
  2. 白名单匹配(whole_match):在句子中间时前后必须有空格在句首或句尾时前后无空格Call Trace: 除外
  3. Debian 白名单(white_debian):完整匹配,关键词前后无空格
  4. 关键词必须用双引号括起,以逗号结尾
  5. 含双引号的关键词需使用转义符 \"

6.3 PCIe 检查规则

PCI 域不使用黑白名单,而是通过 lspci -vvv 获取设备寄存器信息后执行三步硬件级检查

Step 1: 比对 UESta/UEMsk、CESta/CEMsk 寄存器位
        ┌─ Status=+ 且 Mask=- → 进入 Step 2
        └─ 其他 → 正常

Step 2: 判断错误类型
        ┌─ 是 AdvNonFatalErr 或 NonFatalErr → 进入 Step 3
        └─ 不是 → 直接报出异常

Step 3: 检查 UnSupReq
        ┌─ UESta 中 UnSupReq=- → 加报 UnSupReq 异常
        └─ UESta 中 UnSupReq=+ → 忽略(预期行为)

输出格式:[Lspci]: Bus ID: XX abnormal item YY => UESta: [+], UEMsk: [-]


7. 缓存文件 — cache/

文件位置:LogFilterTool/cache/

cache.json

error_key.json 的完整备份。当 error_key.json JSON 解析失败时,read_config() 自动回退到此文件。

keeps.json

[
    "reports/sel.log",
    "reports/sel_vlist.log",
    "reports/sdr.log",
    "reports/pci.log",
    "reports/dmesg.log",
    "reports/messages.log",
    "reports/mcelog.log",
    "reports/errors.log",
    "reports/moc_messages.log",
    "reports/filter_messages.json"
]

定义 --before 清除后需要保留的关键日志文件clear_log(scenario='after', keep=True) 使用此列表通过正则匹配来决定保留哪些文件。

parsers.json

[
    "reports/sel.log",
    "reports/sdr.log",
    "reports/pci.log",
    "reports/dmesg.log",
    "reports/messages.log",
    "reports/mcelog.log"
]

定义 --parse 离线解析模式下必须存在的日志文件parser() 方法在开始过滤前会检查此列表中的所有文件是否存在,任一缺失则报错退出(返回 255)。

mcelog.service

systemd 服务单元模板文件,用于 mcelog daemon 的开机自启配置:

[Unit]
Description=Machine Check Exception Logging Daemon
After=syslog.target

[Service]
Type=forking
ExecStartPre=/etc/mcelog/mcelog.setup
ExecStart=/usr/sbin/mcelog --ignorenodev --daemon --syslog
SuccessExitStatus=0 15
StandardOutput=syslog

[Install]
WantedBy=multi-user.target

注意:此文件目前未被代码直接引用config_mce() 方法走的是 rc.local 路径,而非 systemd 服务路径)。保留此模板作为未来 systemd 集成的参考。


8. CI/CD 流水线 — .gitlab-ci.yml

文件位置:.gitlab-ci.yml

GitLab CI/CD 自动化流水线,在 ipt-gitlab.ies.inventec:8081 上运行。

变量定义

variables:
  sut_ip: "172.17.0.49"
  sut_mac: "00:8c:fa:ef:98:ec"
  reference: "reference.msg"
  script_cmd: "'python LogFilterTool.py --keyverify'"

锚点(YAML Anchors)

锚点 用途
*normal 标准环境:chmod 脚本、Docker 登录/登出、K8S Node4 标签、runner 失败重试 2 次
*tool 工具环境:安装 curl/git/jq/python,clone TOOLS_PROJECT

流水线阶段

lintcheck → runtest → validation → release → cleanup

阶段 1: lintcheck — 代码风格检查

Job: codeReview:Python
镜像: sitpythonlinter:$PYLINT_VER
执行: find . -iname '*.py' | xargs pylint --rcfile=/home/app/pylintrc
触发: 非 triggers 触发

阶段 2: runtest — 自动化测试

Job: runTest
镜像: tool-ansible:$ANSIBLE_VER
流程:
  before_script:
    - git clone $TOOLS_PROJECT
    - sh tool-gitlab-deployment/pipeline_test.sh --before  ← 测试前清除
  script:
    - sh tool-gitlab-deployment/pipeline_script.sh         ← 执行测试
  after_script:
    - sh tool-gitlab-deployment/pipeline_test.sh --after   ← 测试后收集
产物 (expire 4天):
  - ${PWD}/*.*.*.*-Report

阶段 3: validation — 验证

Job: Validation
镜像: tool-ansible:$ANSIBLE_VER
执行: sh tool-gitlab-deployment/pipeline_validation.sh
触发: master / branches / triggers(不含 tags)

阶段 4: release — 发布通知

Job: Release
镜像: tool-gitlab-deployment/docker:18
执行: sh tool-gitlab-deployment/pipeline_mail.sh
触发: 仅 tags

阶段 5: cleanup — 环境清理

Job: cleanEnv
执行: sh tool-gitlab-deployment/pipeline_clean.sh
触发: 非 triggers

.gitignore

/__pycache__/*
__pycache__
*.pyc
*.log

忽略 Python 字节码和所有日志文件。


9. Ansible 集成 — hosts

文件位置:hosts

Ansible 主机清单模板,用于 CI/CD 流水线中连接 SUT:

[validation_server]
<SUT_IP>

[validation_server:vars]
ansible_ssh_pass='<SUT_PASS>'
ansible_ssh_user='<SUT_USER>'
ansible_ssh_port='22'

使用前需将 <SUT_IP><SUT_PASS><SUT_USER> 替换为实际值。

在 runTest 阶段,CI 通过 tool-ansible 镜像中的 Ansible 连接到 SUT,远程执行 LogFilterTool.py。


10. 使用示例

基本用法

查看帮助

$ cd LogFilterTool/
$ python LogFilterTool.py --help

测试前 — 清除系统日志

$ python LogFilterTool.py --before

输出示例:

 ##### Starting clear BMC logs #####
 ##### Starting clear DMESG logs #####
 * Following listed logs were already been cleared: ["sel", "sel_vlist", "sdr", "pci", "dmesg", "messages", "mcelog"]
 * Finished script, please begin any test if needed.

测试后 — 收集并过滤日志

$ python LogFilterTool.py --after

输出示例:

Starting filter & parse [PCI/SEL/dmesg/messages/mcelog] log..
 * Check following logs completed, no error occurs: ["sel", "sel_vlist", ...]

测试后 — 收集但不解析(用于 PowerCycle 多轮测试):

$ python LogFilterTool.py --after --disable-parse

离线解析

在 SUT 上收集

$ python LogFilterTool.py --after --disable-parse

将 LogFilterTool/ 目录拷贝到闲置机器后

$ python LogFilterTool.py --parse

MOC AER 模式(Ali MOC 1.5)

$ python LogFilterTool.py --after --moc

额外输出 reports/moc_messages.logreports/filter_messages.json

验证配置

$ python LogFilterTool.py --keyverify

检查 error_key.json 是否为合法 JSON,结果写入 reports/verify.log

自动确认

$ python LogFilterTool.py --before -y    # 跳过交互式确认

独立使用 PCIe 检查器

$ python lib/FuncParsePci.py -l ./errors.log -d "NVIDIA,Mellanox"

独立使用 MOC 日志解析器

$ python lib/FuncParseSysLog.py AER: "PCIe Error"

独立使用 SEL 详细解析

$ python lib/FuncGetSelEntry.py

11. 参考文档摘要

Donghu SIT Test SOP.pptx

来源:Cui.Davis (2023/10/13),12 页服务器平台 SIT 标准操作流程。

关键流程

步骤 内容 与 LogFilter 的关联
BIOS 配置 VT-d、SR-IOV、Above 4G Decoding 等 硬件基础配置
硬件清单 lspci 枚举所有 PCIe 设备 pci 域使用 lspci -vvv 检查设备寄存器
G4X 诊断 使用 G4X 工具进行硬件诊断 互补工具
LogFilter 清除 测试前 --before 清除日志 直接使用 LogFilter
AC PowerCycle 多轮断电重启测试 产生大量日志 → 推荐使用离线 --parse 模式
LogFilter 收集 测试后 --after 收集过滤 直接使用 LogFilter

Storage HDDS-CONF Function Validation Guide.pdf

来源:8 页,YH V3.0/3.5 存储与网络验证指南(Debian 10)。

关键内容

测试项 工具 方法
网络吞吐 iperf iperf -s (server) / iperf -c (client)
日志过滤 LogFilter 黑/白名单检查 SEL/dmesg/messages/mcelog
OS 压力 stress-ng stress-ng --cpu --io --vm --hdd

12. 版本历史

版本 日期 作者 变更
1.0 2026-05-27 Claude 初始版本,覆盖 SIT-LogFilter 全部功能

开发团队:Liu.AllenJH (Developer), Tong.Anderson (PIC), Li.Victor (Test Leader), Qin.Demo (Tester)

>

最后验证:Qin.Demo on K895G6 (2022-12-07), Result: PASS

>

脚本管理系统ARES Script Management

>

BKM ID1001403 — SIT_LogFilter v6.0