Base Station

Lnav 操作手册

工具

字数统计: 3.2k阅读时长: 12 min
2024/09/14
loading

简介

Lnav(Log File Navigator)是一个开源的命令行工具,专门用于浏览和分析日志文件。它支持多种日志格式,并且能够自动识别和高亮显示关键信息,如日期、时间、日志级别等。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

preview

除了常规的日志打开方式,lnav 还支持 ssh 的路径的实时日志显示,将 filePath 替换成需要的 ssh 地址即可

lnav @ssh_log_path

向一些特殊的需要指令才能获得的本地实时日志,例如 logcat 。可以借助 lnav -e 'command' 来实现,它会监听 command 指令的输出,来进行实时日志的预览.

lnav -e ‘ adb shell logcat -v time’

lnav.gif

主题修改

不同的主题影响代码高亮的颜色风格,默认支持下列主题:

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 工作原理和使用方式。

"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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"std-logcat-time": {
"pattern": "^(?<timestamp>\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3}) (?<level>.{1})/(?<tag>\\S+\\s*)\\((?<pid>\\s?\\d+)\\):(?<body>.*)"
}
}{
"level": {
"kind": "string",
"foreign-key": true
},
"tag": {
"kind": "string",
"identifier": true
},
"pid": {
"kind": "integer",
"identifier": true
},
"body": {
"kind": "string",
"identifier": false
}
}

Lnav 会对所有行的日志都做上述相同的分解整理操作,因此整个日志就被拆解成了一张数据表,查询数据表当然就比纯文本匹配获得更高的上限和灵活性。

录屏-2024年09月04日-15时41分29秒.gif

操作

知道 Lnav 的数据结构后,我们后续的操作也基本是围绕着这些解析的数据来进行。Lnav 的操作基本分为三大类

  1. 文本搜索匹配
  2. 日志简单过滤和格式化日志预览
  3. 内置指令执行
  4. SQL 语句查询

接下来我们对这三块进行分别讲解

搜索

搜索是所有日志工具非常常用的的功能之一, Lnav 也同样具有。在开始介绍搜索的使用之前,要先说明一下 Lnav 的搜索功能只用于搜索,它和过滤功能是分开的,如果你想缩减日志的预览范围应该优先使用指令提到的过滤功能,在此基础上再使用搜索来进一步定位想要查询的日志信息。

Lnav 是在终端中进行预览和操作的,我们通过渐入 / 来进行搜索匹配文本 ,在输入 /MediaPlayService 后我们可以看到以下视图,整个界面被分成了四块区域 LOG Syntax Help Preview Data 以及 Search for

截图 2024-09-04 16-05-09.png

  • Log 区域就是当前的日志区域,之后通过搜索匹配到的具体文本,会在此区域进行单独高亮展示。
  • Syntax Help 区域会介绍搜索的一些正则匹配语法和范例,避免每次都去查找文档来回忆增加使用成本
  • Preview Data 区域会预览陈列匹配到的文本,如果此时 Preview Data 没有展示数据,那么就可以提前调整搜索策略, 通过 CTRL+P 可以控制此区域的显示和隐藏
  • Search for 在输入阶段会提示发起的搜索的快捷键,在发起搜索后,Search for 所属行会展示所匹配到的行数来进行数据参考

发起搜索后,Lnav 会将当前所有匹配到的文本高亮标记,例如下图的通过 onPlayerState state=(\d+) 获得的结果,会将具体的 state 数值进行高亮

截图 2024-09-04 16-27-44.png

通过快捷指令,我们可以快速在各个匹配的搜索标签之间来进行跳转

  • CTRL+J,CTRL+] 跳转到搜索匹配的第一个和最后一个
  • n,N 向下和向上跳转到搜索匹配到的文本
  • < ,> 向左和向右跳转到搜索匹配到的文本

过滤和预览格式内容

通过 p 我们查看当前选中行正则解析的数据,便于我们进行方便的查看日志的各个拆解信息,而针对一些 Json 或者长的 Bean 数据我们可以通过 Shift+P ,来启用整体格式化功能,来更加让我们更加方便的查阅和处理一些长日志,此模式一些长文本和 Json 文本会被 Lnav 分段 解析展示,便于理解和查阅.

录屏-2024年09月04日-17时27分13秒.gif

通过 tab 我们可以打开过滤面板,过滤面板会以列表的形式展示当前的过滤条件,我们可以动态的启用和结合不同的过滤条件,过滤面板的各种操作都已经在 TextFilters 下边进行了提示

  • i/o 创建输入过滤和反过滤词条
  • space 启用/关闭当前选中的过滤词条
  • enter 编辑当前的过滤词条
  • t 调整当前词条为过滤或者反过滤
  • D 删除当前词条
  • f 启用/关闭所有的过滤条件

截图 2024-09-04 18-16-49.png

每个词条都会展示自己的属性,例如命中条数,过滤条件,以及是否启用和作用与过滤还是反过滤

指令

搜索功能并没有很好的利用 Lnav 的格式化功能,过滤功能和日志格式化预览让 Lnav 的功能初露端倪,而 lnav 指令则是能够简单的呈现出 lnav 的效果,通过 : 键入来执行 lnav 的指令。

Lnav 支持的指令很多,像之前的过滤面板的功能也可以通过指令来完成

1
2
3
4
# 只展示匹配了 okhttp 所在的行 
filter-int okhttp
# 之展示不匹配 okhttp 所在的行
filter-out okhttp

除此之外,通过 filter-expr 我们还可以操作 lnav 所解析的各种字段

1
2
3
4
5
:filter-expr :tag = 'XXX'
:filter-expr :pid = 000
:filter-expr :uid = 000
:filter-expr :body REGEXP "Radio"
:filter-expr :tag = 'AndroidRunTime' OR :body REGEXP 'SIG: 9' OR :body REGEXP 'ANR IN'

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 更适合来进行一些复杂的数据统计和输出,具体的查询方式这里就不再赘述。

截图 2024-09-04 16-46-30.png


热键

虽然 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
2
3
SELECT * FROM android_system_logcat_time
SELECT tag,log_body FROM android_system_logcat_time WHERE pid=22492 AND tag LIKE '%Poi%'

隐藏日志

1
2
3
4
5
6
7
8
9
10
11
//隐藏头行之后的行
:hide-lines-after here
//隐藏头行之前的行
:hide-lines-before here

也可以指定固定时间
:hide-lines-after 6am
隐藏未被标记的行
:hide-unmarked-lines
隐藏指定的字段
:hide-fields field-name

执行 cmd 指令

将顶行当作内容执行 cmd 指令

1
2
3
:pipe-line-to shell-cmd

:pipe-line-to sed -e 's/foo/bar/g'

将标记行当作内容执行 cmd 指令

1
2
3
:pipe-to shell-cmd

:pipe-to sed -e s/foo/bar/g

设置 log 显示等级

1
2
3
:set-min-log-level log-level

:set-min-log-level error

转换时间戳

1
2
3
:unix-time seconds

:unix-time 1490191111

写入

将 SQL 结果作为 CSV 写入

1
2
3
:write-csv-to [-onymous ize ] path

:write-csv-to /tmp/table.csv

以表格格式将 SQL 结果作为文件写入

1
2
3
:write-table-to [–anonymize] path

:write-table-to /tmp/table.txt

将 SQL 结果以 JSON 写入

1
: write-json-to [-onymous ize ] path

将标记行以原始文件格式写入

1
2
3
4
5
6
7
8
9
: write-raw-to [-view = { log,db }][-onymous ize ] path

- view = { log,db }-用作数据源的视图

–anonymize — Anonymize the lines

Path * ー要写入的文件的路径

:write-raw-to /tmp/table.txt

将标记行追加到指定文件中

1
2
3
:append-to path

:append-to /tmp/interesting-lines.txt

将显示的文本以原始文件格式写入

1
2
3
: write-screen-to [-onymous ize ] path

:write-screen-to /tmp/table.txt

退出/重建

1
2
:quit
:rebuild
CATALOG
  1. 1. 简介
    1. 1.1. Lnav 的特点
  2. 2. 环境配置
    1. 2.1. 安装
      1. 2.1.1. MacOS
      2. 2.1.2. Linux
    2. 2.2. 主题修改
    3. 2.3. 配置文件
  3. 3. 使用
    1. 3.1. Lnav 如何工作的
    2. 3.2. 操作
      1. 3.2.1. 搜索
      2. 3.2.2. 过滤和预览格式内容
      3. 3.2.3. 指令
      4. 3.2.4. SQL 语句
  4. 4. 热键
    1. 4.1. 导航热键
    2. 4.2. 时间热键
    3. 4.3. 视图热键
  5. 5. 常用命令
    1. 5.0.1. 常用 SQL 指令
    2. 5.0.2. 隐藏日志
  6. 5.1. 执行 cmd 指令
    1. 5.1.1. 将顶行当作内容执行 cmd 指令
    2. 5.1.2. 将标记行当作内容执行 cmd 指令
  7. 5.2. 设置 log 显示等级
  8. 5.3. 转换时间戳
  9. 5.4. 写入
    1. 5.4.1. 将 SQL 结果作为 CSV 写入
    2. 5.4.2. 以表格格式将 SQL 结果作为文件写入
    3. 5.4.3. 将 SQL 结果以 JSON 写入
    4. 5.4.4. 将标记行以原始文件格式写入
    5. 5.4.5. 将标记行追加到指定文件中
    6. 5.4.6. 将显示的文本以原始文件格式写入
    7. 5.4.7. 退出/重建