文章目录
在服务运维、线上问题排查过程中,我们经常需要精准导出某一分钟、某一秒的服务报错日志。很多同学会直接使用grep 匹配时间戳导出日志,但会遇到一个高频问题:只能抓到报错首行,完整的换行异常堆栈信息全部丢失,导致无法定位具体报错原因。
本文分享4个可直接复制使用的精准日志导出命令,完美保留完整异常栈,彻底解决多行日志截取丢失问题。
一、问题复现:为什么常规grep抓不到堆栈?
1. 常规命令
日常排查指定分钟日志,大家常用以下命令:
grep "2026-08-04 01:48:" service.log > service.tmp.log
2. 问题原因
grep 默认的匹配逻辑是:只匹配并输出符合规则的单行内容。
而项目中的异常报错(Java、Python、Go 服务通用)都是多行文本结构:首行是带时间戳的报错信息,后续换行内容为 Exception、Caused by、方法栈、行号等堆栈详情。
常规 grep 只会抓取带时间戳的首行,后续所有换行的核心堆栈信息都会被过滤,最终导出的日志只有报错提示,没有定位问题的关键依据。
二、四种解决方案(直接复制可用)
以下命令适配所有服务日志,针对「指定分钟报错+完整异常堆栈」场景,按需选择即可,优先推荐前两种方案。
方案一:匹配时间行 + 向后抓取N行堆栈(最常用)
通过 -A 参数(After),匹配到目标时间行后,额外抓取后续指定行数,完整覆盖异常堆栈。适合堆栈行数固定、快速排查场景。
# 匹配01:48日志,向后抓取20行堆栈,足够覆盖绝大多数报错
grep -A 20 "2026-08-04 01:48:" service.log > service.tmp.log
参数说明:
-A 20:匹配行之后输出20行内容,堆栈过长可修改为 30、50- 适配场景:单条报错堆栈行数较少、快速导出、批量排查
方案二:精准截取整分钟全部日志(零遗漏,推荐)
使用 sed 区间匹配,精准截取01:48:00 ~ 01:48:59 整一分钟的所有日志,无论单行日志、多行堆栈、连续报错,全部完整保留,无任何遗漏。
sed -n '/2026-08-04 01:48:/,/2026-08-04 01:49:/p' service.log > service.tmp.log
核心优势:
- 完整保留分钟内所有日志、异常堆栈、打印信息
- 无需手动判断堆栈行数,零配置、零遗漏
- 生产环境精准排查首选,适配所有日志格式
方案三:前后上下文抓取(追溯报错前置日志)
部分报错需要结合报错前的请求日志才能定位问题,通过-B(Before)抓取前置行,-A 抓取后置堆栈,还原完整请求链路。
# 抓取报错前2行、报错行、报错后30行堆栈
grep -B 2 -A 30 "2026-08-04 01:48:" service.log > service.tmp.log
参数说明:
-B 2:输出匹配行之前2行日志(追溯请求入参、前置操作)-A 30:输出匹配行之后30行堆栈
方案四:精准过滤异常堆栈(只抓报错,过滤冗余日志)
如果一分钟内日志量极大、正常日志过多,只想导出纯报错+堆栈信息,可通过正则匹配异常关键字,精准过滤有效内容。适配 Java、Python 主流服务异常栈。
grep -E "(2026-08-04 01:48:|Exception|Error|Caused by:|at |\t)" service.log > service.tmp.log
匹配规则:
- 匹配目标时间戳的报错首行
- 匹配 Exception、Error 异常标识
- 匹配 Caused by、at 堆栈关键字、缩进栈行
三、常见问题
问题一:导出日志打开不换行、格式混乱
Linux 日志导出到 Windows 打开后无换行、乱码堆叠,是换行符格式问题,执行以下命令一键修复:
dos2unix zpfilter.tmp.text
问题二:堆栈过长,-A 参数行数不够
直接调大参数即可,常规服务报错 -A 50 可覆盖99%的堆栈场景,超长堆栈可直接使用方案二的 sed 整分钟截取。
发表回复