SIT-LogFilter — 服务器 SIT 测试日志过滤工具使用说明书
1. 概述
SIT-LogFilter 是 Inventec TA Team 开发的服务器 SIT(System Integration Testing)日志过滤工具,版本 Rev: 1.4.17。
核心功能
在服务器 SIT 测试过程中,自动完成以下任务:
- 测试前:清除系统日志(SEL/dmesg/messages/mcelog),确保测试结果不受历史日志干扰
- 测试中:配置并确保 mcelog 守护进程在后台运行
- 测试后:收集 PCI/SEL/SDR/dmesg/messages/mcelog 日志,以
error_key.json为标准执行黑白名单过滤 - 输出:被黑名单命中的日志记录在
reports/errors.log中
支持的客户项目
| 客户 | 状态 |
|---|---|
| Baidu | 支持 |
| Ali | 支持(含 MOC 1.5 AER 过滤) |
| Tencent | 支持 |
| JD | 支持 |
| ByteDance | 支持 |
支持的操作系统
- RHEL/CentOS 6 / 7 / 8
- Debian 9 / 10
技术栈
- 语言:Python 2.7+ / 3.x 兼容
- 并发模型:multiprocessing(Manager + Process),每行日志启动独立进程过滤
- 依赖:ipmitool(BMC 通信)、lspci(PCIe 设备枚举)
本地下载📁 本地下载
提示:点击按钮将打开网络文件夹,点击即可下载
| 文件 | 适用系统 | 版本 |
|---|---|---|
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 时间:
- 在 SUT 上仅收集不解析:
python LogFilterTool.py --after --disable-parse - 将整个脚本包拷贝到闲置机器
- 执行离线解析:
python LogFilterTool.py --parse
4. 主入口 — LogFilterTool.py
文件位置:LogFilterTool/LogFilterTool.py
这是整个工具的入口脚本,包含 Diagnostic 类(12 个方法)、配置读取函数和 CLI 参数解析。
4.1 Diagnostic 类
class Diagnostic(object):
核心诊断类,封装所有日志清除、收集、过滤、检查逻辑。
__init__() — 初始化
- 检测操作系统类型(
getSystem('system')取centos/redhat/debian/ubuntu) - 创建
reports/输出目录 - 写入
errors.log文件头:# BELOW LISTED ARE SYSTEM CHECK ABNORMAL LOGS. - 若 errors.log 已存在则不清除(追加模式)
config_mce() — 配置 mcelog 守护进程
- 检查 OS 版本是否为 6~9 系列(RHEL/CentOS/Debian)
- 检查 mcelog 进程是否已在 daemon 模式运行:
ps -ef | grep -v grep | grep mcelog - 若未运行,执行:
/usr/sbin/mcelog --ignorenodev --daemon --syslog --logfile=/var/log/mcelog - 将启动命令追加到
/etc/rc.local,确保开机自启 - 设置 rc.local 权限为 755
prerequisite(logs) — 测试前日志清除
- 遍历
error_key.json中每个日志域的clear_cmd - 执行清除命令(如
ipmitool sel clear、dmesg -c) - messages 特殊处理:循环清除直到
/var/log/messages为空(防止清除期间新日志写入) - 备份清除前的日志到
backups/<name>_bak.log - 记录操作日志到
reports/SitPreLog.log - 打印清除后的日志文件列表(绿色
*标记)
artifacts(logs) — 测试后日志收集
- 遍历
error_key.json中每个日志域 - 如果有
ipmi_cmd(如 bmc 域):按name: command格式解析 sel_vlist特殊处理:使用SelEntry类做 verbose 解析- 其他:直接
popen(cmd).read() - 否则执行
cmd(如dmesg、lspci -vvv、cat /var/log/mcelog) - messages 特殊处理:
zcat解压所有历史messages.*.gz,再cat当前非 gz 文件 - 结果写入
reports/<name>.log
check_sel() — SEL 日志检查
- 调用
iter_list()以bmc域对sel.log执行黑白名单过滤 - 结果判定:若 errors.log 中
[Sellog]条目数为 0 则 PASS,否则 FAIL
check_sdr(allows) — SDR 日志检查
- 直接读取
sdr.log,过滤掉状态为ok或ns的条目 - 其余条目视为异常,写入
[Sdrlog]标记 - 状态格式:
Sensor | Value | Status,取第 3 列(索引 2)
check_dmesg() — dmesg 日志检查
- 两步过滤:
- 先以
advance模式过滤:检查errors_ignore和errors_fixed列表 - 再以标准模式过滤:黑白名单匹配
- 结果写入
[Dmesg]标记
check_msg() — messages 日志检查
- 调用
iter_list()对messages.log执行 messages 域黑白名单过滤
check_mce() — mcelog 日志检查
- 调用
iter_list()对mcelog.log执行 mcelog 域白名单过滤
check_moc() — MOC AER 日志检查
- 仅在
--moc参数启用时执行 - 调用
SysLogParser类解析 messages 中的 AER 错误 - 按小时统计 AER 发生次数,
<=5为 WARNING,>5为 ERROR - 输出:
reports/filter_messages.json和reports/moc_messages.log
check_pci() — PCIe 设备检查
- 调用
PciParser类检查所有 PCIe 设备的 UESta/UEMsk 和 CESta/CEMsk 寄存器 - 异常写入
[Lspci]标记 - 结果判定:无异常则 PASS
uniq_error() — 错误去重
- 读取
errors.log所有行 - 对
[Lspci]/[Sellog]/[Dmesg]/...标记的条目做去重(比较去掉[Tag]:前缀后的内容) - 非标记行(如 PASS/FAIL 结果行)保留
- 删除原文件后重新写入去重结果
check_error() — 最终错误报告
- 统计
errors.log中所有标记行(匹配正则^\[(Lspci|Moclog|Sellog|Sdrlog|Dmesg|Messages|Mcelog)\]\:\s) - 若 > 0:红色打印
There were error messages been found, please check 'reports/errors.log' - 若 = 0:绿色打印
Check following logs completed, no error occurs
clear_log(scenario, keep) — 日志清理
scenario='before':清空 reports/ 下所有日志(交互式确认)scenario='after':保留 keeps.json 中列出的关键日志keep=True:使用正则^(sel|sdr|pci|dmesg|messages|mcelog)\.log$匹配保留keep=False:删除全部
parser() — 解析编排器
解析主流程,按顺序执行所有检查:
check_sel() → check_dmesg() → check_msg() → check_mce() → check_moc() → check_pci() → uniq_error() → check_error()
- 检查
parsers.json中所有必需日志文件是否存在 - 启动
ThreadBar线程进度条(300 秒超时) - 支持
Ctrl+C中断
4.2 read_config()
模块级函数,负责加载配置。
--keyverify模式:验证error_key.json格式是否正确(try/except JSON 解析),结果写入reports/verify.log- 正常模式:加载
error_key.json;若加载失败则回退到cache/cache.json
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 解释器版本:
- 从
sys.version中提取版本号(如2.7.18) part=0/1/2返回对应段位(主/次/修订版本号)part>2返回完整版本号字符串
getSystem(type='')
检测操作系统版本:
- 从
platform.platform()中提取 OS 信息(如centos-7.6) type='system':返回完整字符串"centos-7"type='series':返回主版本号整数7- 支持识别:redhat、centos、ubuntu、debian
5.3 FuncGetSelEntry.py — SEL 条目解析
文件位置:LogFilterTool/lib/FuncGetSelEntry.py
SelEntry 类
解析 ipmitool sel elist -vvv 输出的详细 SEL 条目。
工作流程:
execute(commands, shell):通过subprocess.Popen执行命令,捕获 stdout 和 stderrparser(key):
- 以
"SEL Next ID:"为分隔符切分 stderr,得到头部信息 + 各条目头部 - 以
'\n\n'(空行)切分 stdout,得到各条目详细内容
output(commands, shell):整合输出 —— 头部 +条目头: 条目内容拼接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
三种匹配方式:
keyword在句子中间(前后有空格)- 句首:
keyword(关键词在开头,紧随空格) - 句尾:
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__() — 多进程调度
- 使用
multiprocessing.Manager().dict()创建共享字典收集结果 - 读取日志文件全部内容,去除非 ASCII 字符:
sub('[^\x00-\x7f]', '', content) - 按行拆分,每行启动一个独立 Process 执行过滤
- 根据
log_type选择 worker 函数:
log_type == 'mcelog'→worker_mce()log_type == 'advance'→worker_adv()- 其他 →
worker()
- 等待所有进程完成(
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
过滤逻辑:
- 遍历每个黑名单关键词(
deny) - 检查该行是否被任一白名单(
whole_match)匹配 →count += 1 - 若
count == 0(未被白名单豁免)且黑名单匹配(deny.lower() in line.lower()),则命中 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 的预过滤阶段(在标准黑白名单之前运行):
errors_ignore:列表中的关键词大小写不敏感匹配 → 视为需要标记的软错误errors_fixed:列表中的关键词精确匹配 → 视为已知但已修复的错误
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() 方法:
- 如果指定了
devices参数,通过lspci | grep -iE "device1|device2|..."筛选目标设备 - 为每个 PCIe 设备启动独立进程执行
pci_worker() - 使用
ProgressBar显示解析进度
pci_log_handle()
解析完成后,若 errors.log 为空则删除文件(无异常时的清理)。
独立运行
FuncParsePci.py 可独立运行:
$ python FuncParsePci.py -l ./errors.log -d "NVIDIA,Mellanox"
参数:
-l / --logname:错误输出文件(默认./errors.log)-d / --devices:逗号分隔的设备过滤列表
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) — 日志解析
- 遍历
/var/log/messages*所有文件(包括轮转文件) - 筛选所有带时间戳的行(匹配
Mon DD HH:MM:SS格式) - 从文件修改时间获取年份
- 对每个匹配关键字的行,计算:
str_time:格式化时间字符串timestamp:Unix 时间戳time_mark:相对于第一条日志的小时偏移量(计算公式:(timestamp - start_timestamp) / 60 / 60,补零对齐)
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(头部提示) |
关键参数:
total:总步数symbol:填充字符(默认━)color:进度条颜色(默认红色\033[1;31m)width:进度条宽度(默认 40)
__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() # 取消事件
wait > 0:倒计时模式,wait 秒后自动完成wait <= 0(如 -1):持续模式,每秒更新,直到cancel.set()pause.set()/pause.clear():暂停/恢复进度stop():调用progress.done()并设置 cancel 事件
在 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.local → ln -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
配置模板差异:
- RHEL 7:
Type=forking,ExecStart=/etc/rc.d/rc.local - RHEL 8:增加了
Documentation和[Install]段(WantedBy=multi-user.target),ExecStart=... start,GuessMainPID=no - Debian 9/10:
ConditionPathExists(而非ConditionFileIsExecutable),StandardOutput=tty,SysVStartPriority=99
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):
- 黑名单匹配:不分大小写,该行含指定单字则匹配
- 白名单匹配(
whole_match):在句子中间时前后必须有空格;在句首或句尾时前后无空格;Call Trace:除外 - Debian 白名单(white_debian):完整匹配,关键词前后无空格
- 关键词必须用双引号括起,以逗号结尾
- 含双引号的关键词需使用转义符
\"
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.log 和 reports/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 ID:1001403 — SIT_LogFilter v6.0