4、日志采集工具:tail、grep、awk、sed 在日志分析中的实战用法
说实话,日志分析这事儿,看着简单,但真到了大屏故障排查的时候,你手速慢一秒,老板的脸色就黑一度。我见过太多人还在用鼠标翻日志,那效率,急死人。
今天咱们就把四个最趁手的工具——tail、grep、awk、sed——在日志分析里的实战用法捋一遍。这些命令我几乎每天都在用,尤其是线上出问题那会儿,它们就是我的救命稻草。
4.1 tail:实时盯梢,看最新日志
tail 是我用得最频繁的命令,没有之一。大屏故障排查时,第一件事就是看最新的报错。
基础用法
# 查看最后100行日志
tail -n 100 app.log
# 实时跟踪日志输出(最常用)
tail -f app.log
我个人习惯用 tail -f 配合 grep 一起用。比如线上报 500 错误,我会这样:
tail -f access.log | grep " 500 "
这样屏幕上只刷出 500 的请求,干净利落。我在项目中遇到过一个问题:日志量太大,tail -f 刷屏太快,根本看不清。后来我加了个 --pid 参数,配合 less 分页,舒服多了。
tail -F(大写 F)代替 tail -f。日志文件如果被轮转(logrotate),tail -f 会跟丢,而 tail -F 会自动跟踪新文件。这个坑我踩过,那次排查到半夜才发现是文件被切了。
4.2 grep:大海捞针,精准定位
grep 就是日志分析里的探照灯。但很多人只会 grep "error",这太糙了。
实战场景: 大屏上突然显示数据库连接失败,你得快速定位所有相关日志。
# 递归搜索所有日志文件
grep -r "Connection refused" /var/log/
# 显示匹配行的前后5行上下文
grep -C 5 "ORA-12541" alert.log
# 只输出匹配的文件名(不输出内容)
grep -l "OutOfMemoryError" *.log
嗯,这里要注意:线上日志文件动辄几个 G,直接 grep 会卡死。我一般先 grep -c 统计一下匹配行数,确认有数据再细查。
# 统计错误出现次数
grep -c "ERROR" app.log
你想想看,如果一次 grep 返回几千行,你根本看不完。这时候我会用 grep -v 排除掉已知的干扰项:
# 排除健康检查的日志
grep -v "healthcheck" app.log | grep "ERROR"
grep -i(忽略大小写)搜 "error",结果把 "ErrorHandler" 这种类名也搜出来了,干扰很大。建议先明确大小写规则,必要时用 -w 做单词匹配。
4.3 awk:结构化提取,按列分析
awk 是日志分析的重武器。日志大多是结构化的,比如用空格或逗号分隔。这时候 awk 就派上大用场了。
实战场景: 分析 Nginx 访问日志,找出响应时间超过 5 秒的请求。
# 假设日志格式:IP 时间 方法 URL 状态 响应时间
# 第6列是响应时间(毫秒)
awk '$6 > 5000 {print $1, $4, $6}' access.log
我在项目中遇到过一个问题:日志里某些字段是空的,awk 默认按空格分割,结果列数对不上。后来我改用 awk -F'|' 指定分隔符,稳了。
更高级的用法: 统计每个接口的调用次数和平均耗时。
# 假设第4列是URL,第6列是耗时
awk '{url[$4]++; time[$4]+=$6} END{for(u in url) print u, url[u], time[u]/url[u]}' access.log | sort -k2 -rn | head -10
说白了,这就是一个迷你版的报表工具。大屏上展示的很多指标,底层就是用 awk 算出来的。
awk 的 BEGIN 和 END 块非常有用。BEGIN 用来初始化变量,END 用来输出汇总结果。我经常在 BEGIN 里设置 FS="," 来指定分隔符。
4.4 sed:流式编辑,批量替换
sed 在日志分析里主要做两件事:过滤和替换。它不像 grep 那样只查,也不像 awk 那样算,它改内容。
实战场景: 日志里 IP 地址需要脱敏,或者时间戳格式需要统一。
# 将IP地址替换为 ***.***.***.***
sed 's/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/***.***.***.***/g' app.log
# 只打印包含 "ERROR" 的行,并删除行号前的空格
sed -n '/ERROR/p' app.log | sed 's/^[ \t]*//'
嗯,这里有个坑:sed 默认是直接修改文件(-i 参数),但线上环境千万别直接改源文件。我习惯先 sed 输出到临时文件,确认没问题再覆盖。
# 安全做法:输出到新文件
sed 's/old/new/g' app.log > app_clean.log
我曾经有一次手滑,sed -i 把配置文件改坏了,服务直接挂掉。从那以后,我养成了先备份再操作的习惯。
tail -f app.log | grep "ERROR" | awk '{print $1, $5}' | sed 's/ERROR/⚠️/g'这样实时日志里只显示错误的时间戳和关键字段,而且把 "ERROR" 替换成了更醒目的符号。
4.5 实战案例:5分钟定位大屏卡顿原因
说个真实案例。有一次大屏突然卡住,数据不刷新了。我接到告警后,按以下步骤排查:
- 看最新日志:
tail -100 /var/log/app/error.log,发现大量 "Timeout waiting for connection"。 - 定位具体接口:
grep "Timeout" access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -5,发现某个报表接口超时最多。 - 检查响应时间:
awk '$7 == "/api/report" {print $NF}' access.log | sort -rn | head -10,发现最慢的请求耗时 30 秒。 - 清理干扰:
sed -i '/healthcheck/d' /var/log/app/debug.log(先备份),缩小排查范围。
整个过程不到 5 分钟。说白了,工具就那几个,关键是你得知道什么时候用哪个。
awk 而用 awk,有时候一个 grep -c 就能搞定的事,别整太复杂。我见过有人用 200 行的 awk 脚本做统计,结果维护起来比写个 Python 脚本还费劲。
好了,这四个工具你掌握了,大屏故障排查时至少能省一半时间。下一章咱们聊聊日志轮转和归档策略,那个也是运维的必修课。