简介
Lnav(Log File Navigator)是一个开源的命令行工具,专门用于浏览和分析日志文件。它支持多种日志格式,并且能够自动识别和高亮显示关键信息,如日期、时间、日志级别等。Lnav 不仅能够显示静态的日志文件内容,还可以实时监控新的日志条目的添加。
Lnav 的特点
Q: Lnav 和 Glogg 比有什么区别?
A: 相较于 Glogg 来说 Lnav 的优势在于可以自动检测和格式化日志格式,格式化日志后,用户可以基于日志格式进行高亮显示,并享受更高级的检索与过滤功能。
例如在 Android 的日志场景下, Lnav 能够严格的按照 TAG 以及 PID UID 等唯一标识进行过滤和匹配搜索,而非传统地通过纯文本。以及通过日志的等级来进行不同等级的日志单独展示等。
除此之外 Lnav 还能够对解析的日志建立数据库,通过 SQL 查询来进行更加复杂的日志分析和数据统计
以及 Lnav 可以查看处理服务器的或者 Android 这种实时更新的日志
Q: Lnav 有什么劣势?
A: 由于 Lnav 需要解析所有的文本来进行格式化,所以它相较于 Glogg 这种在查看数以 GB 的日志文件时性能就十分吃紧了,此时就不建议使用 Lnav.
环境配置
安装
Lnva 只支持 Linux 相关系统,桌面系统例如 Ubuntu/MacOS 可以直接通过包管理命令安装
MacOS
brew install lnav
Linux
sudo install lnav
Ubuntu 系统部分自带了低版本的 lnav ,通过 install 安装无法覆盖掉,如果想要更方便地使用更多特性,建议自行下载替换掉 bin 目录下的 lnav https://lnav.org/downloads
安装完成后即可使用 lnav ,在 terminal 输入 lnav filepath 即可进入 Lnav 的日志窗口
lnav filePath
除了常规的日志打开方式,lnav 还支持 ssh 的路径的实时日志显示,将 filePath 替换成需要的 ssh 地址即可
lnav @ssh_log_path
向一些特殊的需要指令才能获得的本地实时日志,例如 logcat 。可以借助 lnav -e 'command'
来实现,它会监听 command 指令的输出,来进行实时日志的预览.
lnav -e ‘ adb shell logcat -v time’
主题修改
不同的主题影响代码高亮的颜色风格,默认支持下列主题:
default, dracula, eldar, grayscale, monocai, night-owl, solarized-dark, and solarized-light.
在 lnav 视图执行命令即可切换主题
:config /ui/theme {theme_name}
具体的效果和风格差异可以自行体会,如果都不满意也可以自定义主题,参考 https://docs.lnav.org/en/v0.12.0/config.html#theme-definitions 来设置自己的主题配置文件
配置文件
Lnav 默认支持多种日志格式,具体可以查看 https://docs.lnav.org/en/v0.12.2/formats.html
如果 Lnav 不支持你现在使用的日志格式,我们可以通过 Lnva 定制的语法创建一个解析当前日志的配置文件,将配置文件放置到 .lnav/formats/installed
下即可支持
使用
Lnav 的环境就已经搭建完成,我们可以进行通过 Lnav 对日志进行预览了。在日常分析和查看日志过程中我们基本不太关心全局的 log 日志输出,只是需要查阅特定的进程和 tag 。或在这个前提下再进行者进行相关 message 的匹配搜索。下面就来介绍一下 Lnav 工作原理和使用方式。
Lnav 如何工作的
"10-13 15:39:27.517 I/GoogleURLConnFactory( 2118): Using platform SSLCertificateSocketFactory”
上述是一行标准的通过 adb shell logcat -v time
输出的日志,得益于 lnav 的格式化日志,通过上述的配置文件,在 Lnav 加载日志时,我们已经借助 Lnav 将一行日志分解为五个字段
timestamp
level
tag
pid
body
1 | { |
Lnav 会对所有行的日志都做上述相同的分解整理操作,因此整个日志就被拆解成了一张数据表,查询数据表当然就比纯文本匹配获得更高的上限和灵活性。
操作
知道 Lnav 的数据结构后,我们后续的操作也基本是围绕着这些解析的数据来进行。Lnav 的操作基本分为三大类
- 文本搜索匹配
- 日志简单过滤和格式化日志预览
- 内置指令执行
- SQL 语句查询
接下来我们对这三块进行分别讲解
搜索
搜索是所有日志工具非常常用的的功能之一, Lnav 也同样具有。在开始介绍搜索的使用之前,要先说明一下 Lnav 的搜索功能只用于搜索,它和过滤功能是分开的,如果你想缩减日志的预览范围应该优先使用指令提到的过滤功能,在此基础上再使用搜索来进一步定位想要查询的日志信息。
Lnav 是在终端中进行预览和操作的,我们通过渐入 /
来进行搜索匹配文本 ,在输入 /MediaPlayService
后我们可以看到以下视图,整个界面被分成了四块区域 LOG
Syntax Help
Preview Data
以及 Search for
Log
区域就是当前的日志区域,之后通过搜索匹配到的具体文本,会在此区域进行单独高亮展示。Syntax Help
区域会介绍搜索的一些正则匹配语法和范例,避免每次都去查找文档来回忆增加使用成本Preview Data
区域会预览陈列匹配到的文本,如果此时 Preview Data 没有展示数据,那么就可以提前调整搜索策略, 通过CTRL+P
可以控制此区域的显示和隐藏Search for
在输入阶段会提示发起的搜索的快捷键,在发起搜索后,Search for 所属行会展示所匹配到的行数来进行数据参考
发起搜索后,Lnav 会将当前所有匹配到的文本高亮标记,例如下图的通过 onPlayerState state=(\d+)
获得的结果,会将具体的 state
数值进行高亮
通过快捷指令,我们可以快速在各个匹配的搜索标签之间来进行跳转
CTRL+J
,CTRL+]
跳转到搜索匹配的第一个和最后一个n
,N
向下和向上跳转到搜索匹配到的文本<
,>
向左和向右跳转到搜索匹配到的文本
过滤和预览格式内容
通过 p
我们查看当前选中行正则解析的数据,便于我们进行方便的查看日志的各个拆解信息,而针对一些 Json 或者长的 Bean 数据我们可以通过 Shift+P
,来启用整体格式化功能,来更加让我们更加方便的查阅和处理一些长日志,此模式一些长文本和 Json 文本会被 Lnav 分段 解析展示,便于理解和查阅.
通过 tab
我们可以打开过滤面板,过滤面板会以列表的形式展示当前的过滤条件,我们可以动态的启用和结合不同的过滤条件,过滤面板的各种操作都已经在 TextFilters 下边进行了提示
i/o
创建输入过滤和反过滤词条space
启用/关闭当前选中的过滤词条enter
编辑当前的过滤词条t
调整当前词条为过滤或者反过滤D
删除当前词条f
启用/关闭所有的过滤条件
每个词条都会展示自己的属性,例如命中条数,过滤条件,以及是否启用和作用与过滤还是反过滤
指令
搜索功能并没有很好的利用 Lnav 的格式化功能,过滤功能和日志格式化预览让 Lnav 的功能初露端倪,而 lnav 指令则是能够简单的呈现出 lnav 的效果,通过 :
键入来执行 lnav 的指令。
Lnav 支持的指令很多,像之前的过滤面板的功能也可以通过指令来完成
1 | # 只展示匹配了 okhttp 所在的行 |
除此之外,通过 filter-expr 我们还可以操作 lnav 所解析的各种字段
1 | :filter-expr :tag = 'XXX' |
SQL 语句
SQL 语句通过 ;
键入来触发执行,SQL 的执行结果与平常的日志预览面板是单独分开的,我们可以通过 SQL 语句进入 SQL 执行面板,或是通过 v
键我们也可以直接跳转到 SQL 的面板。SQL 面板基于性能考虑默认是不展示数据的。
SQL 的表名默认为你当前格式化的文件名称
例如触发了 android_system_logcat_time 表名就为 android_system_logcat_time
通过 ;
命令可以执行 SQL 语句查询,按 V 进入查询结果
通过 SELECT * FROM android_system_logcat_time
预览整个日志 SQL 表,SQL 的使用的 Sqlite 语法,SQL 更适合来进行一些复杂的数据统计和输出,具体的查询方式这里就不再赘述。
热键
虽然 Lnav 在新的版本支持了鼠标操作部分视图,但是毕竟是在 terminal 中运行的程序,Lnav 也内置了大量的快捷键和指令,熟练的应用分析处理日志起来会事半功倍,接下来就介绍一下常用的快捷键位和指令
导航热键
热键1 | 热键2 | Command | |
---|---|---|---|
Space | 下一页 | ||
b | backspace | 上一页 | |
j | ↓ | 下一行 | |
k | ↑ | 上一行 | |
g | 日志头 | ||
G | 日志尾 | ||
e | Shift + e | 上一个/下一个错误 | |
w | Shfit + w | 上一个/下一个警告 | |
n | Shift + n | 上一个/下一个搜索命中 | |
o | Shift + o | 按 pid 进行跳转检索 | |
> | < | 横向 | 上一个/下一个搜索命中 |
u | Shift + U | 上一个/下一个书签 | |
m | Shift + m | 标记当前行书签 | |
ctrl+l | 切换到简单模式,方便复制 | ||
/ | 正则匹配搜索 | ||
: | 指令输入 | ||
; | 输入 SQL | ||
{ | } | 历史的上一个/下一个位置 |
时间热键
热键 | 热键2 | Command |
---|---|---|
7 | 8 | 前/后一份分钟 |
r | Shift + r | 通过上次与 goto 命令一起使用的相对时间向前/向后。 |
:goto 14:51:05.254 | 前往指定的时间 |
视图热键
热键 | 热键2 | Command |
---|---|---|
tab | 查看当前的过滤器 | |
q | 退出当前视图 | |
p | 查看选中行日志详情 | |
shift+p | 查看选中行完整的格式化日志 | |
i | Shift + i | 日志随时间的分布图 |
v | Shift + v | sql 视图 |
常用命令
常用 SQL 指令
1 | SELECT * FROM android_system_logcat_time |
隐藏日志
1 | //隐藏头行之后的行 |
执行 cmd 指令
将顶行当作内容执行 cmd 指令
1 | :pipe-line-to shell-cmd |
将标记行当作内容执行 cmd 指令
1 | :pipe-to shell-cmd |
设置 log 显示等级
1 | :set-min-log-level log-level |
转换时间戳
1 | :unix-time seconds |
写入
将 SQL 结果作为 CSV 写入
1 | :write-csv-to [-onymous ize ] path |
以表格格式将 SQL 结果作为文件写入
1 | :write-table-to [–anonymize] path |
将 SQL 结果以 JSON 写入
1 | : write-json-to [-onymous ize ] path |
将标记行以原始文件格式写入
1 | : write-raw-to [-view = { log,db }][-onymous ize ] path |
将标记行追加到指定文件中
1 | :append-to path |
将显示的文本以原始文件格式写入
1 | : write-screen-to [-onymous ize ] path |
退出/重建
1 | :quit |