Clloz's Blog

Back

日志查看与分析:从过滤到多窗口排查 日志查看与分析:从过滤到多窗口排查

面对一个几百 MB 甚至数 GB 的日志文件,直接用编辑器打开通常不是最有效的办法。日志来源越多、格式越混乱,越需要先区分几个不同的任务:寻找文件、过滤内容、连续阅读、定位异常,以及对照多个时间线。

一套实用的日志工作流可以概括为:

找到日志 → 清洗或归一化 → 过滤目标内容 → 阅读上下文 → 多文件关联分析
text

不同工具负责其中不同的环节。理解它们的边界,比记住大量命令更重要。

常用工具的定位#

rg:快速过滤内容#

ripgreprg)适合从一个或多个文件中筛选包含特定模式的行:

rg 'ERROR|timeout' app.log
rg '\[ROS\]' logs/
rg '/database/config' --glob '*.log'
bash

它速度快、支持正则表达式,也能递归搜索目录,但它的核心职责是过滤,而不是长时间阅读日志。可以把它理解成查询中的 WHERE

fd 与 fzf:寻找文件和交互筛选#

fd 用来快速查找文件:

fd --extension log
fd 'mapping|server' logs/
bash

fzf 则为命令输出增加交互式模糊筛选:

fd --extension log | fzf
rg --files logs/ | fzf
bash

二者经常组合使用:fd 负责提供候选项,fzf 负责从候选项中快速选择。

less:连续阅读大文件#

less 不会一次性把整个文件加载到内存,适合通过 SSH 阅读较大的日志:

less -R app.log
bash

进入 less 后,可以使用:

/keyword    向后搜索
?keyword    向前搜索
n           跳到下一个匹配项
N           跳到上一个匹配项
G           跳到文件末尾
g           跳到文件开头
text

如果只是阅读单个日志并查看异常前后的上下文,rgless 往往已经足够。

Neovim:需要编辑器能力时的分析工作台#

当排查过程需要多个 buffer、分屏、临时标记或复杂搜索时,可以在 Neovim 中同时打开多个专题日志:

nvim ros.log api.log error.log
bash

Neovim 适合处理经过过滤、大小可控的文件。对超大原始日志,先用 rgsed 或专用脚本缩小范围,通常比直接加载更稳妥。

Quickfix:在匹配结果之间导航#

Quickfix 保存的是一组带有文件名、行号、列号和文本的定位信息。它适合“找到一批异常,然后逐项检查”,而不是代替日志阅读器。

如果 Neovim 的 grepprg 已配置为 rg,可以执行:

:grep ERROR logs/**/*.log
:copen
:cnext
:cprev
vim

也可以从 Telescope 的搜索结果发送到 Quickfix。具体快捷键取决于个人配置;很多配置使用 <C-q> 完成这一步。

Trouble 可以为诊断、Quickfix 和位置列表提供更友好的界面,但它没有改变底层数据的性质。是否安装 Trouble,主要取决于是否需要更直观的结果浏览体验。

lnav 能自动识别多种常见日志格式,并提供时间排序、过滤、字段解析和 SQL 查询等能力:

lnav /var/log/nginx/*.log
bash

它尤其适合 Nginx、Apache、syslog 等格式稳定的日志。对于无法识别的自定义格式,可以先转换成统一格式,也可以为 lnav 编写格式定义。

三种常见工作流#

普通应用日志#

对于格式相对规范的 Node.js、Go、Python 或 Java 服务日志,可以先搜索异常,再阅读上下文:

rg -n 'ERROR|WARN|timeout' app.log
less -R app.log
bash

如果已知错误发生的大致时间,可以直接缩小范围:

rg '2026-05-30 14:2[0-9]' app.log > incident.log
less -R incident.log
bash

需要统计时,可以继续使用管道:

rg 'status=500' access.log | wc -l
bash

systemd 与实时日志#

查看 systemd 服务时,应先让 journalctl 完成服务和时间范围筛选:

journalctl -u nginx --since '30 minutes ago'
journalctl -u my-service -f
bash

还可以继续交给 rg 过滤。实时管道需要启用行缓冲,否则输出可能不会及时出现:

journalctl -u my-service -f | rg --line-buffered 'ERROR|timeout'
bash

普通文件的实时跟踪可以使用:

tail -F app.log | rg --line-buffered 'ERROR|WARN'
bash

这里使用 -F 而不是 -f,是为了在日志轮转、文件被重新创建后继续跟踪。

多来源、分段或乱序日志#

移动端、WebView、后端服务和设备端日志混在一起时,问题通常不在查看器,而在原始数据缺少统一结构。例如,一份日志可能同时包含:

  • Android 系统输出;
  • Web 端日志;
  • 被拆成多行的 JSON;
  • 不同模块各自生成的时间戳;
  • 到达顺序与事件发生顺序不一致的数据。

这种情况下,应该先编写脚本完成归一化:

  1. 丢弃确认无关的系统噪声;
  2. 合并具有相同请求 ID 的分段内容;
  3. 解析并统一时间戳;
  4. 按事件时间排序;
  5. 输出一份可搜索的标准日志。

假设清洗后得到 mapping-app.log,可以继续生成不同专题的日志:

rg '\[ROS\]' mapping-app.log > ros.log
rg '\[API\]' mapping-app.log > api.log
rg -i 'error|timeout|"success":false' mapping-app.log > error.log
rg '15:24:' mapping-app.log > timeline.log
bash

然后利用 tmux 或 Neovim 分屏对照:

┌─────────────────────┬─────────────────────┐
│ ros.log             │ api.log             │
├─────────────────────┼─────────────────────┤
│ timeline.log        │ error.log           │
└─────────────────────┴─────────────────────┘
text

此时真正提升效率的是“先结构化,再按主题拆分,最后对照时间线”,而不是某个特定的界面插件。

一套可以直接采用的选择顺序#

面对陌生日志时,可以按以下顺序判断:

  1. fd 找到相关文件;
  2. rg 判断错误是否存在并缩小范围;
  3. less 阅读单个大文件的上下文;
  4. 用 Neovim 对照多个过滤后的文件;
  5. 需要逐项跳转时,把结果放入 Quickfix;
  6. 日志结构稳定且数量较多时,尝试 lnav;
  7. 原始日志混乱时,优先编写清洗和归一化脚本。

日志中经常包含令牌、Cookie、用户数据、内网地址和请求参数。将日志复制到工单、聊天工具或公开文章之前,应先做脱敏处理。

总结#

日志排查不是“选择哪个查看器”,而是建立一条合适的处理流水线:

日志源 → 结构化 → 过滤 → 阅读 → 导航 → 关联分析
text

rgless、Neovim、Quickfix 和 lnav 并不互相替代。让每个工具只负责自己擅长的环节,才能在日志体积和来源不断增加时,仍然保持清晰、可重复的排查过程。

日志查看与分析:从过滤到多窗口排查
https://clloz.com/blog/log-view
Author Clloz
Published at May 30, 2026
Comment seems to stuck. Try to refresh?✨