志诊 LogMedic:把 Windows 事件日志里那 96% 的噪声筛掉

项目地址:ghostgorge/LogMedic: LogMedic

一个用 Python 写的 Windows 日志分析与系统运维工具。零第三方依赖,单文件 exe,内置 100 条事件 ID 知识库、45 个蓝屏停止码和 23 套处置方案。


一、起因:打开事件查看器,然后呢?

电脑动不动重启、开机越来越慢、某个软件老是崩。老手会说:去看事件查看器。

于是你打开了 eventvwr.msc,展开”Windows 日志 → 系统”,看到密密麻麻一屏红叉。然后呢?

我在一台正常办公用的 Dell OptiPlex 上做了个统计。最近 30 天,”系统”和”应用程序”两个日志里,错误和警告一共 3900 条。按出现次数排序,前五名是这样的:

排名事件来源 / ID30 天次数实际影响
1Security-SPP / 8229274
2FilterManager / 11273
3DistributedCOM / 10016157
4DistributedCOM / 10010155
5Kernel-PnP / 219104

前五名加起来 963 条,全是噪声。

  • Security-SPP 8229:”规则引擎未能执行一项或多项计划的操作,错误代码 0x80080005″。只要 slmgr /xpr 显示系统已激活,这条就没有任何实际影响。
  • DCOM 10016:微软官方文档白纸黑字写着,这类事件在多数情况下可以安全忽略 —— 系统内置组件的默认 DCOM 权限本来就是不完整的。
  • Kernel-PnP 219 + WUDFRd + 0xC0000365:蓝牙/传感器类设备的用户模式驱动框架提示,设备都正常就不用管。

而同一份日志里,真正要命的东西是这几条:

事件30 天次数说明
Kernel-Power 414系统 4 次没正常关机就重启了
EventLog 60082上次关机是意外的
volmgr 1614蓝屏转储文件创建失败

噪声占了 96%,真问题只有 4%,而且排在列表最底下。

这就是事件查看器最大的问题:它不是看不到数据,是数据太多。一个普通用户按”错误数量”排序去排查,会花一整天折腾 DCOM 权限(改注册表所有者、进组件服务配权限),然后什么也没解决——因为他压根没注意到那 4 次异常重启。

志诊 LogMedic 就是为了解决这一件事:替你做判断,而不是替你翻日志。


二、它是怎么判断的

2.1 按知识库定级,不按日志级别

这是整个工具的地基。举三个例子:

事件事件查看器里的级别实际含义工具的定级
Ntfs / 98信息“卷运行状况良好,无需执行任何操作”忽略(这是好消息)
DistributedCOM / 10016警告微软说可忽略噪声,不扣分
disk / 7错误磁盘有坏块严重,最高优先级

这三条在事件查看器里长得差不多,但严重程度天差地别。工具内部给每条知识库条目打了 ig(可忽略)标记——被标记为可忽略的事件,无论刷出多少条都不会升级、不会扣健康分,只在报告末尾单独列一个”可忽略的日志噪声”分区。

这条设计有个很实际的理由:为了消灭日志里的红叉去改系统设置,是运维里最常见的无用功,工具不该带着用户往坑里走。

2.2 必须按”来源 + 事件 ID”两个字段一起匹配

这是开发中最早撞到的坑。同一台机器上:

 Hyper-V-Hypervisor / 129  →  "虚拟机监控程序已初始化 I/O 重新映射"(信息级,完全正常)
 storahci / 129           → "将设备复位"(硬盘即将出问题的强信号)

只按事件 ID 认,会把好事报成故障。 网上很多”事件 ID 大全”就是这么错的。所以知识库的主键是 (来源, 事件ID),来源匹配做了一档放宽(Microsoft-Windows-Ntfs 能匹配 Ntfs),但绝不跨 ID 猜。

2.3 聚合与关联

50 条 7031 不是 50 个问题,是 1 个问题。工具会:

  • Service Control Manager 7031/7034服务名归类,告诉你”哪 3 个服务崩了,各崩了几次”
  • Application Error 1000出错模块归类——这才是定位应用崩溃的关键字段
  • Kernel-Power 41 + BugCheck 1001 + EventLog 6008 + volmgr 161 识别成同一次蓝屏的四个侧面,合并成一条结论

还有一条容易被忽略的细节:7023 事件如果错误文本是”系统正在关机”,那是关机时的正常收尾,工具会直接跳过它,不计入服务异常。

2.4 健康分

100 分制,按严重度扣分,每档有封顶(避免一类问题把分数扣穿)。出现次数少于 5 次的问题按半价扣——否则”一次 SxS 报错”和”两周内 166 次服务启动失败”扣一样的分,分数就失去意义了。但严重级别不打折:一次蓝屏就是一次蓝屏

那台样本机器最终得分 43 分(问题较多),扣分明细:

 -18  检测到 4 次异常重启(无蓝屏转储)
  -8 有 7 个服务启动失败或超时(共 166 次)
  -8 应用程序崩溃 44 次
  -8 有 1 个服务意外终止(共 32 次)
  -4 蓝屏转储文件写入失败
  ...

三、一个真实案例:查出了因果链

样本机器上有 4 条 volmgr 161「转储文件创建失败」。工具去读了转储配置,发现:

 转储类型      : 内核内存转储
 小转储目录   : D:\Minidump
 页面文件     : D:\pagefile.sys 16384MB
 系统盘 C:     : 没有页面文件

于是给出了这条结论:

页面文件不在系统盘 C: 上。 内核转储必须先写入系统盘的页面文件(崩溃时写进去,重启后再搬成 MEMORY.DMP),否则每次蓝屏都会写失败——对应 System 日志里的 volmgr 161。

因果链完整闭合了:有人把页面文件整个挪到了 D 盘 → 系统盘上一个都不留 → 内核转储物理上无法写出 → 4 次异常重启一份证据都没留下 → 蓝屏原因永远查不出来。

而 Windows 对此没有任何提示。你只会在日志深处看到一条”转储文件创建失败”,如果不知道这个机制,根本联想不到是页面文件位置的问题。

这就是我想做这个工具的原因:这类知识不难,但分散在几十篇英文文档和论坛帖子里,普通人凑不齐。


四、功能

工具有六个页面。

一键体检

点一下,30~40 秒出结果:半环表盘显示健康分,下面按严重度列出所有结论,每条都能展开看”现象 / 可能原因 / 影响 / 建议处置”。

采集范围是 Windows 四大日志 + 26 个精选的”应用程序和服务日志”通道(任务计划、启动性能、NTFS、存储、更新、组策略、无线、打印、远程桌面等)。不是全量扫 1000 多个通道——那样既慢又全是噪声。

另外单独捞一遍”级别不是错误、但对定位问题极其关键”的事件,比如 Kernel-Power 41User32 1074(谁发起的关机)、EventLog 6005/6006(开关机标记)。这些在按级别筛选时全部会被漏掉。

事件浏览

按事件查看器的习惯做的两级通道树(Windows 日志 / 应用程序和服务日志)。可以按级别、时间范围、关键词筛选,双击看完整描述和原始 XML。

每条事件下面直接挂知识库解读——选中一条 7009,右侧就告诉你这是”等待服务连接超时(30000 毫秒)”,常见原因是什么,要不要管。

支持导入 .evtx 文件离线分析(同事发来的日志、从故障机导出的日志都能直接看),也支持把任意通道导出成 .evtx 归档。

诊断与修复

结论 + 处置方案。每条结论关联对应的一键方案,也可以只看手动步骤自己动手。

蓝屏分析

  • 检查并一键修复转储配置
  • 不装 WinDbg 直接解析 minidump:Windows 内核转储文件开头是 DUMP_HEADER64 结构,固定偏移上就放着停止码和四个参数
 0x00  签名 'PAGE'
 0x04 'DU64'(64 位)
 0x38 BugCheckCode           ← 停止码在这
 0x40/0x48/0x50/0x58         ← 四个参数
 0xF98 DumpType
  • 扫描转储体里的 .sys 文件名,用一份微软自带驱动白名单过滤,把第三方驱动挑出来并标注归属(klif.sys → 卡巴斯基,nvlddmkm.sys → NVIDIA 显卡驱动,vboxdrv.sys → VirtualBox)
  • 崩溃时间线:列出每次崩溃前 10 分钟内的所有事件——崩溃前最后写日志的组件,往往就是元凶

这不能替代 WinDbg 的栈回溯,但足够回答用户最关心的两个问题:什么码、哪些第三方驱动在场

服务与计划任务

服务列表带”可执行文件是否还存在”判断,能一眼找出软件卸载后残留的幽灵服务——那是 7000/7009 报错最常见的来源。可以直接改启动类型、启停服务。

计划任务列表把上次运行结果翻译成中文

 0x80070569  →  登录失败:用户未被授予请求的登录类型
 0x8007010B → 目录名称无效(「起始于」没填)
 0x80040154 → 类未注册(COM 组件缺失或未注册)
 0x41303     → 任务尚未运行过(这是正常状态,不是失败)

还有开机耗时趋势。这里有个坑:官方的 Diagnostics-Performance/Operational 通道在较新的 Windows 11 上已经不存在了(样本机 26220 版本上查不到),所以做了退路——用 Kernel-General 12(系统启动)到该次启动后第一条 Winlogon 通知的时间差做估算,并明确标注”估算”,不冒充精确值。

知识库

可全文搜索。输入 7009 直接跳到对应事件,输入 0x7E 跳到蓝屏停止码,输入”计划任务”列出所有相关条目。

内容数量
事件 ID 条目100
蓝屏停止码45
处置方案23
专题文章10

专题包括:看懂 Windows 事件日志(必读基础)、蓝屏完整排查流程、开机慢/关机慢、系统卡顿、服务问题速查、计划任务失败速查、可以放心忽略的日志噪声清单、常见错误码速查、机器可能被入侵的迹象、月度巡检清单。

每个蓝屏停止码给四样东西:这码在说什么、最可能的原因(按实际遇到的概率排序,不按微软文档的顺序)、四个参数怎么读、一步步怎么办。


五、”一键修复”的安全边界

这是我在这个项目上花心思最多的地方。一个能改系统的工具,最怕的不是功能少,是乱动手

规则是死的:

1. 三级风险,高风险的根本不给一键按钮。

23 套方案里,12 套 safe(只读诊断)、10 套 caution(会改系统状态)、1 套 dangerdanger 那套是 DCOM 10016 权限修改——涉及改注册表所有者和 COM 权限,工具只显示手动步骤,绝不代劳,而且开头第一句就是”推荐做法是直接忽略它”。

2. 默认预演。

勾着”预演”时只打印将要执行的完整命令行,不做任何实际改动。用户看明白了再取消勾选执行。

3. 执行前摊开命令。

不存在”点一下,然后不知道它干了什么”。每一步执行前,完整命令行都打在输出区里。

4. 谨慎级建议先建系统还原点。

界面上有勾选框,工具会调 Checkpoint-Computer。建不成(系统保护没开、24 小时内已建过)会如实告诉你,不假装成功。

5. 全程留痕。

所有实际执行过的命令写进 %APPDATA%\LogMedic\actions.log。出了问题能回溯”工具到底动了什么”。

还有一条判断上的克制:工具不会因为”自动启动的服务没在运行”就建议你禁用它——除非它的可执行文件确实已经不存在了。因为触发启动型服务停着是完全正常的。


六、技术实现

6.1 技术栈

选择
语言Python 3.8+
界面tkinter / ttk(标准库)
日志采集PowerShell Get-WinEvent
打包PyInstaller,单文件 exe
第三方依赖

代码约 10000 行,打包后 exe 约 9.5 MB。

日志采集走 PowerShell 而不是直接调 Windows API,是因为只有 Get-WinEvent 能把事件渲染成本地语言的可读描述wevtutil 导出的 XML 里只有参数,没有渲染后的文本——而描述文本恰恰是最有价值的部分(错误码、文件名、模块名、服务名都在里面)。

知识库全部是 .py 模块,不是 JSON 数据文件。因为单文件 exe 里读数据文件要走 _MEIPASS 取路径,是打包翻车的经典来源。写成模块,import 就完事了。

6.2 开发中撞出来的三个坑

这三个都是在真机上跑出来才发现的,写在这里给同类项目省点时间。

坑一:Windows 事件日志的 XPath 查询最多只允许 23 个表达式。

 # System 通道要查 27 个事件 ID,一次查下去 —— 返回 0 条
 # 加了 -ErrorAction SilentlyContinue 之后连报错都看不到,纯静默失败

超限后整条查询作废,而 -ErrorAction SilentlyContinue(为了容忍”没找到事件”这种正常情况,必须加)会把错误吞掉,表现为静默返回 0 条,极难排查。解决办法是主动分块,一块最多 16 项(给 LogName、时间范围留余量),再合并去重。

坑二:PowerShell 里 try/catch 是语句不是表达式。

 # 这样写会直接抛「哈希文本不完整」的解析错误,整段脚本作废
 [pscustomobject]@{
   install = try { $os.InstallDate.ToString('yyyy-MM-dd') } catch { '' }
 }

必须先算成变量再引用。这个错误的杀伤力在于它是解析期错误——不是那一个字段取不到值,是整个脚本一行都不执行。

坑三:服务的 PathName 不能按空格切。

 "C:\Program Files\App\svc.exe" -k netsvcs     ← 带引号
 C:\Program Files\App\svc.exe -k netsvcs       ← 不带引号但含空格
 \SystemRoot\System32\drivers\x.sys           ← 驱动

按空格切第二种会得到 C:\Program,于是所有装在 Program Files 下的服务都会被判定为”可执行文件不存在”,工具就会建议用户把一大批正常服务禁用掉。这种误判比不检查更糟。修法是优先按引号取,其次按 .exe/.sys/.dll 结尾的正则取。

顺带一提:中文 Windows 的控制台代码页是 GBK,PowerShell 的 stdout 管道按 GBK 编码出来,中文事件描述会直接乱码。所有需要文本结果的地方,都让脚本 Out-File -Encoding utf8 写临时文件,Python 再用 utf-8-sig 读回来。而 .ps1 脚本文件本身如果不带 BOM,PowerShell 5.1 会按 ANSI 解析,脚本里的中文同样会烂掉——写脚本时必须用 utf-8-sig

6.3 自检

selftest.py 有 16 项无界面自检,打包前后都会跑。其中有一条比较特别:

喂进 80 条纯噪声事件,健康分必须 ≥ 95。

这条守的是工具的判断力底线——防止哪天改坏了规则,让工具开始拿噪声吓唬用户。


七、用法

图形界面

双击 LogMedic.exe。打包时带了 uac_admin,启动会先弹 UAC——建议用管理员身份运行,否则读安全日志、解析 minidump、执行修复都会受限。

非管理员也能用,标题栏会标注”[非管理员 · 部分功能受限]”,只读诊断类的方案照常可以跑。

命令行

logmedic-cli.exe --report            # 直接生成 HTML 巡检报告
logmedic-cli.exe --report out.html # 指定输出路径
logmedic-cli.exe --selftest # 跑一遍自检

--report 这个模式适合塞进计划任务里定期跑,报告存档。巡检最值钱的用法是留痕——出问题时你能翻出”上个月还好好的”那个时间点。

报告

HTML 报告是自包含的:样式内联、不引任何外部资源,双击就能看,也能直接发给同事或打印成 PDF。另有纯文本版,方便贴到工单或聊天里。


八、局限

说清楚它不能做什么,比吹它能做什么重要:

  • 不能替代 WinDbg。 蓝屏分析只读转储文件头和驱动名单,没有栈回溯。真正复杂的蓝屏还是得上 WinDbg。
  • 知识库覆盖不了长尾。 100 条事件 ID 覆盖的是高频问题。第三方软件写的事件(那台样本机上还有 10 类未收录)工具会老实说”未收录”,并建议你拿”来源 + 事件ID”去搜——而不是编一个看起来很像的解释。
  • 规则匹配不是推理。 它给的是经验规则的结论,涉及硬件更换、系统重装这类重大决定前,请再做人工确认。
  • 只支持 Windows。 依赖 Get-WinEvent,Windows 10 / 11 / Server 2016+ 上验证过。

九、写在最后

做这个工具的过程中,我越来越确信一件事:运维工具的价值不在于能显示多少信息,而在于敢不敢替用户把信息删掉。

事件查看器什么都给你看,所以它什么都没告诉你。志诊 LogMedic 的 3900 条事件里,最后只呈现十几条结论,剩下的要么被合并,要么被明确标注为”可以忽略,别管它”。

判断力就是敢做减法。


志诊 LogMedic v1.0.0 · Python + tkinter · 单文件 exe,无需安装 · 适用于 Windows 10 / 11 / Server 2016+