服务崩了但日志有10个G,怎么快速找到关键信息

凌晨收到告警,服务挂了。登上服务器一看,日志文件10个G,怎么快速定位问题?

日志分析的正确姿势

很多人看日志就是cat xxx.log | grep error,日志小还行,日志大了直接卡死。下面这些技巧能帮你快速定位问题。

一、系统日志分析(journalctl)

现在大多数Linux发行版都用systemd管理服务,日志统一由journald收集。

基础用法

# 查看所有日志
journalctl

# 查看最近的日志(最常用)
journalctl -e

# 实时跟踪日志
journalctl -f

# 查看指定服务的日志
journalctl -u nginx
journalctl -u mysql

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

# 查看今天的日志
journalctl --since today

# 查看指定时间段
journalctl --since "2024-01-01 10:00:00" --until "2024-01-01 12:00:00"

按优先级过滤

# 只看错误级别以上
journalctl -p err

# 优先级:
# emerg(0) - 系统不可用
# alert(1) - 必须立即处理
# crit(2) - 严重错误
# err(3) - 错误
# warning(4) - 警告
# notice(5) - 正常但重要
# info(6) - 信息
# debug(7) - 调试

# 看err和以上级别(crit, alert, emerg)
journalctl -p err..emerg

按进程/用户过滤

# 按PID
journalctl _PID=12345

# 按用户
journalctl _UID=1000

# 按程序名
journalctl _COMM=java

输出格式

# JSON格式(方便脚本处理)
journalctl -o json

# 紧凑JSON(一行一条)
journalctl -o json-pretty

# 短格式(默认)
journalctl -o short

# 显示完整时间戳
journalctl -o short-iso

二、应用日志分析技巧

1. 快速定位错误

# grep -n 显示行号
grep -n "ERROR" app.log

# 显示错误及后10行(看堆栈)
grep -A 10 "Exception" app.log

# 显示错误及前后各5行(看上下文)
grep -C 5 "ERROR" app.log

# 统计错误次数
grep -c "ERROR" app.log

2. 按时间范围提取

日志格式通常是2024-01-01 10:00:00这样的,可以用sed提取:

# 提取10:00到11:00的日志
sed -n '/2024-01-01 10:00/,/2024-01-01 11:00/p' app.log

# 更精确的方式:用awk
awk '/2024-01-01 10:00/,/2024-01-01 11:00/' app.log

3. 统计分析

# 统计每小时错误数量
grep "ERROR" app.log | awk '{print $2}' | cut -d: -f1 | sort | uniq -c

# 统计最频繁的错误类型
grep "Exception" app.log | sort | uniq -c | sort -rn | head -20

# 统计请求响应时间分布
grep "cost=" app.log | awk -F'cost=' '{print $2}' | cut -d' ' -f1 | \
  awk '{
    if($1<100) a++;
    else if($1<500) b++;
    else if($1<1000) c++;
    else d++
  } END {
    print "<100ms:", a;
    print "100-500ms:", b;
    print "500-1000ms:", c;
    print ">1000ms:", d
  }'

4. 大文件处理技巧

# 只看最后1000行
tail -n 1000 app.log

# 只看最后5分钟(假设日志在持续写入)
tail -f app.log  # 实时跟踪

# 用less替代cat(可以搜索和翻页)
less app.log
# 在less中:
# /ERROR  搜索ERROR
# n       下一个匹配
# N       上一个匹配
# G       跳到文件末尾
# g       跳到文件开头

# 并行处理大文件
zgrep "ERROR" app.log.*.gz  # 同时搜索多个压缩文件

三、日志轮转配置(logrotate)

日志不轮转,磁盘迟早爆。

配置文件位置

/etc/logrotate.conf         # 主配置
/etc/logrotate.d/           # 各应用配置目录

实用配置示例

# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily                   # 每天轮转
    rotate 30               # 保留30份
    compress                # 压缩旧日志
    delaycompress           # 延迟一次压缩(方便查看昨天的日志)
    missingok               # 日志不存在也不报错
    notifempty              # 空文件不轮转
    create 644 appuser appgroup  # 新日志文件权限
    dateext                 # 用日期作为后缀
    dateformat -%Y%m%d      # 日期格式
    
    postrotate              # 轮转后执行的命令
        /bin/kill -USR1 $(cat /var/run/myapp.pid 2>/dev/null) 2>/dev/null || true
    endscript
}

手动测试轮转

# 测试(不实际执行)
logrotate -d /etc/logrotate.d/myapp

# 强制执行一次
logrotate -f /etc/logrotate.d/myapp

四、实时日志监控

多文件同时监控

# 同时看多个日志
tail -f /var/log/app1.log /var/log/app2.log

# 用multitail(更强大)
# 安装:yum install multitail
multitail /var/log/app1.log /var/log/app2.log

带颜色高亮

# 安装ccze
# yum install ccze

# 带颜色查看日志
tail -f app.log | ccze -A

# 或者用grep高亮
tail -f app.log | grep --color=always -E "ERROR|WARNING|"

五、日志集中管理方案

单机日志好处理,机器多了就得集中管理。

方案一:rsyslog转发

# 客户端 /etc/rsyslog.conf
*.* @日志服务器IP:514        # UDP
*.* @@日志服务器IP:514       # TCP

# 服务端 /etc/rsyslog.conf
$ModLoad imudp
$UDPServerRun 514

方案二:Filebeat + ELK

更现代的方案,适合大规模日志收集。

# filebeat.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/myapp/*.log
  fields:
    app: myapp
    env: prod

output.elasticsearch:
  hosts: ["elasticsearch:9200"]

六、实战:一次OOM问题的日志排查

问题现象

应用偶发性重启,怀疑OOM。

排查步骤

Step 1:查系统日志

# 查看最近的OOM记录
journalctl -k | grep -i "oom\|kill"

# 或者
dmesg | grep -i "oom\|kill"

# 输出:
# Jan 01 03:45:23 server kernel: Out of memory: Killed process 12345 (java)

确认是OOM。

Step 2:看是谁触发的

journalctl -k --since "2024-01-01 03:40:00" --until "2024-01-01 03:50:00"

# 关键信息:
# memory cgroup out of memory
# oom_score_adj: 0
# Memory cgroup stats...

Step 3:分析应用日志

# 找到OOM前的应用日志
tail -n 10000 app.log | less

# 搜索内存相关
grep -E "memory|heap|OutOfMemory" app.log

Step 4:结论

根据日志分析,发现OOM前有大量数据查询请求,导致堆内存暴涨。

远程日志查看

如果管理多台服务器,每次都要SSH上去看日志很麻烦。我现在用星空组网把几台服务器组在一起,本地可以直接用rsync同步日志下来分析,也可以配置集中日志收集,方便很多。

常用命令速查

# 系统日志
journalctl -u nginx -f                    # 实时看nginx日志
journalctl -p err --since "1 hour ago"    # 最近1小时的错误

# 应用日志
tail -f app.log | grep --color ERROR      # 实时看错误
grep -A 20 "Exception" app.log            # 看异常堆栈
awk '/10:00/,/11:00/' app.log            # 提取时间段

# 日志统计
grep -c "ERROR" app.log                   # 错误计数
sort | uniq -c | sort -rn                 # 统计排序

# 大文件
less +G app.log                           # 直接跳到文件末尾
zgrep "ERROR" app.log.gz                  # 搜索压缩文件

总结

场景 推荐工具 命令示例
系统/服务日志 journalctl journalctl -u nginx -p err
实时跟踪 tail -f tail -f app.log | grep ERROR
大文件浏览 less less +G app.log
时间段提取 awk/sed awk '/10:00/,/11:00/' log
统计分析 awk+sort awk '{print $1}' | sort | uniq -c
压缩文件 zgrep zgrep "ERROR" *.gz

排查思路:先定位时间范围,再按关键字过滤,最后看上下文。别一上来就全量搜索,日志大了会很慢。

posted @ 2025-12-09 14:05  花宝宝  阅读(14)  评论(0)    收藏  举报