4、日志分析入门:系统日志(syslog/messages)、应用日志、日志级别与过滤技巧

日志这东西,平时没人搭理它。但系统一出事,它就是你唯一的救命稻草。我见过太多运维新手,服务器挂了第一反应是重启,重启完又挂了,然后一脸懵。其实日志早就把答案写好了,就看你愿不愿意看。

这一章,咱们就聊聊怎么看日志、怎么从海量信息里捞出真正有用的东西。

4.1 系统日志:syslog 与 messages

Linux 系统日志,说白了就是内核和系统服务的「日记本」。它记录着谁登录了、哪个服务挂了、硬盘有没有报错。我个人习惯,排查问题第一步永远是翻系统日志。

不同发行版,日志存放位置略有差异:

发行版 主日志文件 说明
CentOS / RHEL 6 /var/log/messages 系统通用日志,包含内核、服务、认证等
CentOS / RHEL 7+ /var/log/messages 依然保留,但部分日志被 journald 接管
Ubuntu / Debian /var/log/syslog 相当于 CentOS 的 messages
所有发行版 /var/log/dmesg 内核环缓冲区日志,主要记录硬件和驱动信息

嗯,这里要注意:dmesg 记录的是内核启动以来的信息,不会持续增长。而 messagessyslog 是滚动写入的,会按天或按大小切割。

实战经验:有一次线上数据库突然变慢,我查了半天应用日志没发现问题。最后看了一眼 /var/log/messages,发现大量 kernel: INFO: task mysqld:xxxx blocked for more than 120 seconds。这是典型的 I/O 瓶颈,磁盘扛不住了。如果只看应用日志,你永远找不到根因。

4.2 应用日志:别只盯着系统日志

系统日志告诉你「系统层面发生了什么」,但业务层面的问题,得看应用日志。比如 Nginx 的访问日志、MySQL 的慢查询日志、Java 应用的堆栈日志。

应用日志的位置通常由开发者或运维人员自定义,但有几个常见套路:

  • Web 服务: /var/log/nginx/access.log、/var/log/httpd/error_log
  • 数据库: /var/log/mysql/error.log、/var/log/mariadb/mariadb.log
  • Java 应用: 通常在应用目录下的 logs/ 文件夹,或者由 log4j/logback 配置指定
  • 容器化应用: docker logs 或 kubectl logs 直接查看标准输出

你想想看,如果用户反馈「页面打不开」,你去看系统日志,大概率啥也看不到。这时候应该直奔 Nginx 的错误日志,看看是不是 502 或者连接超时。

我的习惯:排查问题时,我会同时开三个终端窗口。一个看系统日志(tail -f /var/log/messages),一个看应用日志(tail -f /var/log/nginx/error.log),一个执行测试命令。这样能快速定位问题出在哪个层面。

4.3 日志级别:从 DEBUG 到 FATAL

日志级别这东西,说白了就是给日志贴了个「重要性标签」。不同级别的日志,代表不同的严重程度。我刚开始做运维时,经常被海量的 INFO 日志淹没,后来才学会按级别过滤。

常见的日志级别(从低到高):

级别 含义 什么时候用
DEBUG 调试信息 开发阶段,排查具体逻辑问题
INFO 普通信息 记录正常操作,如请求到达、任务完成
WARN 警告 可能有问题但不影响运行,如磁盘使用率超过80%
ERROR 错误 功能不可用,如数据库连接失败
FATAL 致命错误 程序无法继续运行,如内存溢出

syslog 也有自己的级别体系,从 emerg(紧急)到 debug(调试),共 8 级。不过现在很多应用都直接使用上面那套标准。

避坑指南:我曾经遇到一个案例,开发同学把所有日志都设成了 INFO 级别,生产环境一天产生 50GB 日志。磁盘写满后,服务直接挂了。记住:生产环境建议设置为 WARN 或 ERROR,DEBUG 日志只在排查问题时临时开启。

4.4 过滤技巧:从海量日志里捞出关键信息

日志文件动辄几百 MB,甚至 GB 级别。你不可能一行一行看。这时候就需要一些过滤技巧。

4.4.1 grep:最基础的过滤

grep 是日志分析的瑞士军刀。我个人最常用的几个组合:

# 查找包含 "error" 的行(忽略大小写)
grep -i "error" /var/log/messages

# 查找包含 "error" 或 "failed" 的行
grep -E "error|failed" /var/log/messages

# 查找不包含 "INFO" 的行(排除干扰)
grep -v "INFO" app.log

# 查找某个时间段的日志
grep "2024-01-15 14:" /var/log/nginx/access.log

4.4.2 tail + grep:实时监控

排查正在发生的问题时,我喜欢用 tail -f 配合 grep

# 实时查看错误日志
tail -f /var/log/messages | grep -i "error"

# 只看某个关键词的实时日志
tail -f /var/log/nginx/access.log | grep "500"

4.4.3 awk 和 sed:进阶处理

有时候需要提取特定字段,或者格式化输出。awk 和 sed 就派上用场了:

# 提取第1列和第3列(假设日志以空格分隔)
awk '{print $1, $3}' /var/log/messages

# 统计某个错误出现的次数
grep "OutOfMemoryError" app.log | wc -l

# 替换敏感信息(比如 IP 地址)
sed 's/192\.168\.1\.[0-9]*/***.***.***.***/g' app.log

4.4.4 journalctl:systemd 时代的日志工具

如果你用的是 CentOS 7+ 或 Ubuntu 16.04+,系统日志已经被 systemd-journald 接管了。这时候 journalctl 比直接看文件更方便:

# 查看所有日志(默认显示最近的)
journalctl

# 查看某个服务的日志
journalctl -u nginx.service

# 查看最近 10 分钟的日志
journalctl --since "10 min ago"

# 查看某个时间段的日志
journalctl --since "2024-01-15 14:00" --until "2024-01-15 15:00"

# 只显示错误级别以上的日志
journalctl -p err

小技巧:journalctl 默认会分页显示,如果你想把日志导出到文件分析,记得加 --no-pager 参数:journalctl -u nginx.service --no-pager > nginx.log

4.5 日志分析的黄金法则

最后分享几条我这些年总结的经验:

  1. 先看时间戳:问题发生的时间点前后 5 分钟的日志,是重点排查区域。
  2. 从高到低过滤:先看 FATAL/ERROR,再看 WARN,最后才看 INFO。别一开始就被海量信息带偏。
  3. 关注上下文:单条日志往往看不出问题,要看它前后 5-10 行的内容。我习惯用 grep -A 5 -B 5 "error" 来查看上下文。
  4. 不要只看一个日志:系统日志、应用日志、访问日志,三者要对照着看。很多时候,问题需要跨日志才能定位。
  5. 日志轮转别忽略:如果当前日志文件没有异常,记得看看被压缩的历史日志。问题可能发生在几天前,只是今天才暴露出来。

日志分析说白了就是「找不同」。正常情况下的日志是什么样的,异常情况又是什么样的。多对比、多积累,你自然就能一眼看出问题所在。嗯,这一章就到这里,下一章咱们聊聊更具体的故障排查流程。