前言:日志分析,为何是系统管理员的核心能力

在运维Linux服务器的过程中,当故障发生时,最先检查的就是日志(Log)。日志就像是系统留下的"黑匣子",记录着什么事件在何时以何种方式发生。无论是追踪安全事件的原因、调试服务故障,还是定位性能瓶颈,日志都是分析的起点。

然而在实际生产环境中,日志文件可能从数GB增长到数十GB,一天积累数百万行也并不罕见。能够从这些海量数据中快速准确地提取所需信息,正是系统管理员和DevOps工程师的核心能力。

本指南将系统性地介绍Linux日志分析所需的所有核心命令。从基础命令到高级单行命令,以可在实际工作中直接复制使用的实战示例为中心进行组织。从初级到中级以上的实战人员都可以按层次进行学习。

1. Linux 日志系统的架构与核心文件

1.1 日志系统的架构

Linux的日志系统大致分为两种体系:

  • 传统 syslog 系列:rsyslog、syslog-ng等以文本文件形式记录日志,存储在/var/log/目录下。
  • systemd-journald:在基于systemd的系统中以二进制格式管理日志,使用journalctl命令进行查询。

大多数现代发行版(RHEL 8+、Ubuntu 20.04+、Debian 11+)都同时使用两套系统。journald先进行一次收集,然后rsyslog再将其保存为文本文件。

1.2 必须了解的核心日志文件

日志文件 内容 主要用途
/var/log/syslog 系统整体消息(Debian/Ubuntu) 常规故障分析
/var/log/messages 系统整体消息(RHEL/CentOS) 常规故障分析
/var/log/auth.log 认证/登录相关(Debian/Ubuntu) 安全分析、入侵检测
/var/log/secure 认证/登录相关(RHEL/CentOS) 安全分析、入侵检测
/var/log/kern.log 内核消息 硬件、驱动问题
/var/log/dmesg 启动时内核消息 启动问题、硬件检测
/var/log/cron cron任务执行记录 定时任务调试
/var/log/maillog 邮件服务器日志 邮件发送/接收追踪
/var/log/nginx/ Nginx访问/错误日志 Web流量分析
/var/log/apache2/ Apache访问/错误日志 Web流量分析
/var/log/mysql/ MySQL/MariaDB日志 DB查询、错误分析
/var/log/audit/audit.log SELinux/AppArmor审计日志 安全审计、策略违规
/var/log/boot.log 服务启动日志 服务启动失败分析
/var/log/lastlog 最后登录记录(二进制) 使用lastlog命令查询
/var/log/wtmp 登录/注销历史(二进制) 使用last命令查询
/var/log/btmp 失败的登录尝试(二进制) 使用lastb命令查询
TIP: 日志文件的位置可能因发行版而异。养成先用ls -la /var/log/确认存在哪些日志文件的习惯。

1.3 理解日志轮转

日志文件由logrotate定期进行轮转(rotation)。之前的日志以.1.2.gz扩展名保存:

# 日志轮转示例
/var/log/syslog          # 当前日志
/var/log/syslog.1        # 上一个日志(未压缩)
/var/log/syslog.2.gz     # 更早的日志(已压缩)
/var/log/syslog.3.gz     # 更早以前的日志(已压缩)

# 搜索压缩日志文件时使用 zgrep、zcat
zgrep "error" /var/log/syslog.2.gz
zcat /var/log/syslog.3.gz | grep "kernel"

# 检查 logrotate 配置
cat /etc/logrotate.conf
ls /etc/logrotate.d/

2. 基本日志查看命令

2.1 tail - 实时日志监控的起点

tail是日志分析中最基本且使用最多的命令。尤其是-f选项,是实时监控的核心。

# 查看最后10行(默认)
tail /var/log/syslog

# 查看最后50行
tail -n 50 /var/log/syslog
tail -50 /var/log/syslog          # 简写形式

# 实时日志监控(follow)
tail -f /var/log/syslog

# 实时 + 从最近100行开始查看
tail -n 100 -f /var/log/syslog
tail -100f /var/log/syslog        # 简写形式

# 同时监控多个文件
tail -f /var/log/syslog /var/log/auth.log

# 文件被替换(rotate)后继续追踪
tail -F /var/log/syslog            # 大写 -F:重新打开文件

# 实时过滤特定关键词
tail -f /var/log/syslog | grep --line-buffered "error"
tail -f /var/log/syslog | grep --line-buffered -i "fail\|error\|warn"
注意:tail -fgrep通过管道连接时,务必使用--line-buffered选项。否则可能因缓冲导致输出延迟。

2.2 head - 查看文件头部

# 查看前10行(默认)
head /var/log/syslog

# 查看前30行
head -n 30 /var/log/syslog

# 除最后10行外的全部内容
head -n -10 /var/log/syslog

2.3 cat、less、more - 查看完整文件

# 输出整个文件(仅适用于小文件)
cat /var/log/cron

# 带行号输出
cat -n /var/log/cron

# 按页浏览(最推荐)
less /var/log/syslog
# less 内部快捷键:
#   / : 向前搜索
#   ? : 向后搜索
#   n : 下一个搜索结果
#   N : 上一个搜索结果
#   G : 跳到文件末尾
#   g : 跳到文件开头
#   q : 退出

# 在less中实时监控(类似tail -f)
less +F /var/log/syslog
# Ctrl+C切换到浏览模式,Shift+F重新进入追踪模式
TIP: 大型日志文件请务必使用less而不是catcat会将整个文件加载到内存中,对于数GB的文件可能会给系统带来负担。

2.4 wc - 快速查看日志统计

# 查看总行数
wc -l /var/log/syslog

# 快速了解今天有多少错误
grep -c "error" /var/log/syslog
grep -ci "error\|fail\|critical" /var/log/syslog

# 比较多个日志文件的行数
wc -l /var/log/syslog /var/log/auth.log /var/log/kern.log

3. grep - 日志搜索的核心武器

grep可以说是日志分析中最重要的命令。通过字符串模式匹配,可以从海量日志中快速提取所需信息。

3.1 基本搜索

# 搜索特定字符串
grep "error" /var/log/syslog

# 忽略大小写搜索
grep -i "error" /var/log/syslog

# 显示行号
grep -n "error" /var/log/syslog

# 仅显示匹配计数
grep -c "error" /var/log/syslog

# 仅显示不包含该字符串的行(反向匹配)
grep -v "info" /var/log/syslog

# 完全单词匹配(匹配error,不匹配errorlog)
grep -w "error" /var/log/syslog

3.2 使用正则表达式的高级搜索

# 使用扩展正则表达式(-E 或 egrep)
grep -E "error|fail|critical" /var/log/syslog

# 搜索IP地址模式
grep -E "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" /var/log/auth.log

# 过滤特定时段的日志(例如:凌晨3点)
grep "^Mar  7 03:" /var/log/syslog

# 日期 + 时间范围(2点~5点)
grep -E "^Mar  7 0[2-5]:" /var/log/syslog

# 提取SSH登录失败记录
grep "Failed password" /var/log/auth.log

# 追踪特定用户的sudo命令
grep "sudo.*username" /var/log/auth.log

3.3 上下文搜索 - 了解错误前后的状况

# 显示匹配行之后5行(After)
grep -A 5 "kernel panic" /var/log/kern.log

# 显示匹配行之前3行(Before)
grep -B 3 "OOM" /var/log/syslog

# 前后各显示5行(Context)
grep -C 5 "segfault" /var/log/syslog

# 复合条件:包含error且与nginx相关
grep "error" /var/log/syslog | grep "nginx"

# 同时搜索多个文件
grep -r "connection refused" /var/log/
grep -rl "connection refused" /var/log/    # 仅输出文件名

3.4 在压缩日志中搜索

# 直接在gz压缩文件中搜索
zgrep "error" /var/log/syslog.2.gz

# 查看压缩文件内容
zcat /var/log/syslog.2.gz | less

# 同时搜索当前和历史日志
zgrep "error" /var/log/syslog /var/log/syslog.1 /var/log/syslog.*.gz

4. awk - 日志数据提取与处理的利器

awk是一种专为按字段分割和处理文本而优化的工具。在提取日志中的特定列或按条件进行统计时非常强大。

4.1 基本字段提取

# syslog格式:日期 主机 进程:消息
# $1=月, $2=日, $3=时间, $4=主机, $5=进程

# 仅提取时间和消息
awk '{print $3, $5, $0}' /var/log/syslog | tail -20

# 仅输出特定字段(Nginx access log示例)
# 格式:IP - - [日期] "请求" 状态码 大小 "Referer" "UA"
awk '{print $1, $9}' /var/log/nginx/access.log    # IP和状态码

# 处理制表符分隔文件
awk -F'\t' '{print $1, $3}' logfile.tsv

# 逗号分隔(CSV)
awk -F',' '{print $1, $NF}' logfile.csv    # 第一个和最后一个字段

4.2 条件过滤

# 仅提取HTTP 500错误(Nginx/Apache)
awk '$9 == 500' /var/log/nginx/access.log

# 所有500系列错误
awk '$9 >= 500 && $9 < 600' /var/log/nginx/access.log

# 仅响应大小超过1MB的
awk '$10 > 1048576' /var/log/nginx/access.log

# 仅特定IP的请求
awk '$1 == "192.168.1.100"' /var/log/nginx/access.log

# 包含特定字符串的行(类似grep)
awk '/error/' /var/log/syslog
awk '/error/ && /nginx/' /var/log/syslog    # AND条件
awk '/error/ || /warn/' /var/log/syslog     # OR条件

4.3 汇总与统计

# 按IP统计请求次数(Top访问IP)
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# 仅用awk进行IP计数
awk '{ip[$1]++} END {for (i in ip) print ip[i], i}' /var/log/nginx/access.log | sort -rn | head -20

# 按状态码统计数量
awk '{code[$9]++} END {for (c in code) print c, code[c]}' /var/log/nginx/access.log | sort -k2 -rn

# 按时段统计请求数(每小时)
awk '{split($4, a, ":"); hour=a[2]; h[hour]++} END {for (i in h) print i, h[i]}' /var/log/nginx/access.log | sort

# 总传输字节数汇总
awk '{sum += $10} END {printf "Total: %.2f GB\n", sum/1024/1024/1024}' /var/log/nginx/access.log

# 按URL路径统计请求数(不区分GET/POST)
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -30

4.4 实战单行命令

# 查找慢请求(假设日志格式包含响应时间)
# 如果log_format中$request_time是最后一个字段:
awk '{if ($NF > 3.0) print $0}' /var/log/nginx/access.log

# 计算每分钟请求数
awk '{split($4,a,"[:/]"); min=a[2]":"a[3]":"a[4]" "a[5]":"a[6]; m[min]++} END {for (i in m) print i, m[i]}' /var/log/nginx/access.log | sort | tail -20

# 计算错误率
awk '{total++; if ($9 >= 400) errors++} END {printf "Total: %d, Errors: %d, Rate: %.2f%%\n", total, errors, (errors/total)*100}' /var/log/nginx/access.log

5. sed - 日志文本转换与提取

sed是流编辑器,在转换日志数据或提取特定范围时非常有用。

5.1 基本模式替换与提取

# 特定字符串替换(用于输出)
sed 's/error/ERROR/gi' /var/log/syslog | head

# 仅输出特定范围的行
sed -n '100,200p' /var/log/syslog          # 第100~200行

# 仅提取特定模式之间的内容
sed -n '/Start of backup/,/End of backup/p' /var/log/syslog

# 提取特定时间范围
sed -n '/Mar  7 14:00/,/Mar  7 15:00/p' /var/log/syslog

# 删除空行
sed '/^$/d' /var/log/application.log

# 删除注释行(#)
sed '/^#/d' /etc/rsyslog.conf

# IP地址掩码(用于安全报告)
sed -E 's/([0-9]+\.[0-9]+\.[0-9]+\.)[0-9]+/\1***/g' /var/log/auth.log

5.2 多重命令与高级用法

# 一次执行多个替换
sed -e 's/error/ERROR/gi' -e 's/warning/WARNING/gi' /var/log/syslog

# 删除特定行(排除第1~5行后输出)
sed '1,5d' /var/log/syslog

# 日期格式转换示例
echo "2026/03/07 14:30:00" | sed 's|\([0-9]*\)/\([0-9]*\)/\([0-9]*\)|\1-\2-\3|'

# 仅输出包含特定模式的行(类似grep)
sed -n '/OOM/p' /var/log/syslog

6. sort、uniq、cut - 日志数据排序与汇总

这三个命令单独使用时也很有用,但通过管道组合使用时才能发挥真正的威力。

6.1 sort - 排序

# 基本排序(字母顺序)
sort /var/log/auth.log

# 逆序排列
sort -r /var/log/auth.log

# 按数字排序
sort -n data.log

# 按特定字段排序(第3个字段,数字逆序)
sort -t' ' -k3 -rn access.log

# 按日期排序
sort -k1,1M -k2,2n /var/log/syslog    # 月(Month)+ 日(数字)

6.2 uniq - 去重与计数

# 去重(必须与sort配合使用!)
sort /var/log/auth.log | uniq

# 显示重复次数
sort /var/log/auth.log | uniq -c

# 按重复次数重新排序(频率排序)
sort /var/log/auth.log | uniq -c | sort -rn

# 仅显示重复的行
sort /var/log/auth.log | uniq -d

# 仅显示唯一的行(只出现1次)
sort /var/log/auth.log | uniq -u
注意: uniq仅去除连续的重复行。务必先执行sort再使用uniq,才能得到正确的结果。

6.3 cut - 字段截取

# 按特定分隔符提取字段
cut -d' ' -f1 /var/log/nginx/access.log        # 仅提取IP
cut -d':' -f1 /etc/passwd                       # 仅提取用户名

# 按字符位置提取
cut -c1-15 /var/log/syslog                      # 前15个字符(日期时间)

# 同时提取多个字段
cut -d' ' -f1,4,7 /var/log/nginx/access.log    # 第1、4、7个字段

6.4 组合管道实战示例

# SSH登录失败IP Top 10
grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -10

# 按时段统计错误数量
grep -i "error" /var/log/syslog | awk '{print $3}' | cut -d: -f1 | sort | uniq -c | sort -rn

# Nginx请求URL Top 20
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20

# 唯一IP访问数
awk '{print $1}' /var/log/nginx/access.log | sort -u | wc -l

# 按日期统计日志行数趋势
awk '{print $1, $2}' /var/log/syslog | sort | uniq -c

7. journalctl - systemd日志分析的全面指南

在基于systemd的系统中,journalctl是最强大的日志查看工具。它以结构化形式查询二进制日志,并原生支持多种过滤功能。

7.1 基本查询

# 查看全部日志
journalctl

# 从最新的日志逆序查看
journalctl -r

# 仅查看最近50行
journalctl -n 50

# 实时监控(与tail -f相同)
journalctl -f

# 特定启动会话的日志
journalctl -b              # 当前启动
journalctl -b -1           # 上一次启动
journalctl --list-boots    # 启动历史列表

# 不使用分页器输出(用于脚本)
journalctl --no-pager

7.2 基于时间的过滤

# 特定日期之后
journalctl --since "2026-03-07"

# 特定时间范围
journalctl --since "2026-03-07 14:00" --until "2026-03-07 16:00"

# 相对时间
journalctl --since "1 hour ago"
journalctl --since "30 min ago"
journalctl --since "2 days ago"
journalctl --since yesterday
journalctl --since today

7.3 基于服务/单元的过滤

# 仅查看特定服务的日志
journalctl -u nginx.service
journalctl -u sshd.service
journalctl -u mysql.service

# 同时查看多个服务
journalctl -u nginx.service -u php-fpm.service

# 实时监控特定服务
journalctl -u nginx.service -f

# 特定服务的最近错误
journalctl -u nginx.service -p err -n 50

7.4 优先级(严重程度)过滤

# 按严重程度级别过滤
# 0=emerg, 1=alert, 2=crit, 3=err, 4=warning, 5=notice, 6=info, 7=debug

journalctl -p emerg          # 紧急(系统不可用)
journalctl -p alert          # 需要立即处理
journalctl -p crit           # 严重状态
journalctl -p err            # 错误(最常用)
journalctl -p warning        # 警告

# 指定范围(仅crit及以上的严重日志)
journalctl -p crit..emerg

# 服务 + 严重程度 + 时间组合
journalctl -u sshd.service -p err --since "1 hour ago"

7.5 输出格式控制

# JSON格式输出(便于解析)
journalctl -u nginx.service -o json-pretty -n 5

# 简洁的单行格式
journalctl -o short-precise

# 可用的输出格式
# short         : 默认syslog风格
# short-precise : 微秒级时间
# short-iso     : ISO 8601格式时间
# verbose       : 显示所有字段
# json          : JSON格式(单行)
# json-pretty   : JSON格式(缩进)
# cat           : 仅消息内容(无时间戳)

# 基于特定字段的过滤
journalctl _COMM=sshd               # 进程名
journalctl _PID=1234                 # PID
journalctl _UID=0                    # root用户
journalctl _HOSTNAME=webserver01     # 主机名

7.6 内核日志与磁盘使用量

# 仅内核消息(类似dmesg)
journalctl -k
journalctl --dmesg

# 查看日志磁盘使用量
journalctl --disk-usage

# 清理日志(删除旧日志)
sudo journalctl --vacuum-time=7d     # 删除超过7天的日志
sudo journalctl --vacuum-size=500M   # 删除超过500MB的部分

8. 按实战场景分类的日志分析

8.1 SSH暴力破解攻击分析

# 检查失败的SSH登录尝试
grep "Failed password" /var/log/auth.log | tail -20

# 提取攻击IP并按频率排序
grep "Failed password" /var/log/auth.log | \
  awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -20

# 分析特定IP的尝试时段
grep "Failed password" /var/log/auth.log | \
  grep "192.168.1.100" | awk '{print $1, $2, $3}'

# 确认成功的登录
grep "Accepted" /var/log/auth.log | tail -20

# 使用异常用户名的攻击尝试
grep "Invalid user" /var/log/auth.log | \
  awk '{print $8}' | sort | uniq -c | sort -rn | head -20

# 按时段统计攻击频率(每小时)
grep "Failed password" /var/log/auth.log | \
  awk '{print $3}' | cut -d: -f1 | sort | uniq -c | sort -rn

# 使用journalctl分析SSH
journalctl -u sshd.service -p warning --since "24 hours ago" --no-pager

8.2 Web服务器故障分析(Nginx/Apache)

# 定位500错误发生时间
grep '" 500 ' /var/log/nginx/access.log | tail -30

# 计算5xx错误比率
awk '{total++; if ($9 ~ /^5/) err++} END {printf "Total: %d, 5xx: %d (%.2f%%)\n", total, err, err/total*100}' \
  /var/log/nginx/access.log

# 分析错误发生的URL模式
grep '" 500 ' /var/log/nginx/access.log | \
  awk '{print $7}' | sort | uniq -c | sort -rn | head -20

# 分析Nginx错误日志
grep "error" /var/log/nginx/error.log | tail -30

# 检查upstream超时
grep "upstream timed out" /var/log/nginx/error.log | wc -l

# 计算每秒请求数(RPS)
awk '{split($4,a,"[:/]"); sec=a[4]" "a[5]":"a[6]":"a[7]; s[sec]++} END {for (i in s) print i, s[i]}' \
  /var/log/nginx/access.log | sort | tail -20

# 特定时段的慢请求(request_time为最后一个字段)
awk '$NF > 5.0 {print $4, $7, $NF}' /var/log/nginx/access.log | tail -20

8.3 磁盘I/O及OOM(内存不足)分析

# 检查OOM Killer终止进程的历史
grep -i "oom" /var/log/syslog
grep "Out of memory" /var/log/syslog
dmesg | grep -i "oom"

# 被OOM终止的进程列表
grep "Killed process" /var/log/syslog | \
  awk -F'[()]' '{print $2}' | sort | uniq -c | sort -rn

# 使用journalctl检查OOM
journalctl -k | grep -i "oom"
journalctl -k | grep "Out of memory"

# 磁盘相关错误
grep -i "I/O error" /var/log/syslog
grep -i "ext4.*error" /var/log/syslog
dmesg | grep -i "error"

# 检测文件系统切换为只读
grep "Remounting filesystem read-only" /var/log/syslog

8.4 服务启动/停止/崩溃追踪

# 服务启动/停止历史
journalctl -u nginx.service | grep -i "started\|stopped\|failed"

# 分析服务失败原因
systemctl status nginx.service
journalctl -u nginx.service --since "10 min ago" -p err

# 分析服务重启频率
journalctl -u mysql.service | grep -c "Started"

# 检查核心转储
journalctl | grep "core dump"
coredumpctl list                    # 使用systemd-coredump时

# 启动失败的服务列表
systemctl --failed

8.5 cron任务调试

# 查看cron执行历史
grep CRON /var/log/syslog
grep CRON /var/log/cron                  # RHEL/CentOS

# 检查特定用户的cron执行
grep "CRON.*username" /var/log/syslog

# 仅查看cron错误
grep CRON /var/log/syslog | grep -i "error\|fail"

# 使用journalctl查看cron
journalctl -u cron.service --since today

# 检查特定脚本的cron执行
grep "backup.sh" /var/log/syslog

9. 高级分析技巧与单行命令集锦

9.1 使用xargs和find进行多文件分析

# 在最近24小时内修改的日志文件中搜索error
find /var/log -name "*.log" -mtime -1 -exec grep -l "error" {} \;

# 在所有日志文件中搜索特定IP
find /var/log -type f -name "*.log" | xargs grep -l "192.168.1.100" 2>/dev/null

# 查找超过特定大小的日志文件
find /var/log -type f -size +100M -exec ls -lh {} \;

# 清理旧日志文件(30天以上)
find /var/log -name "*.gz" -mtime +30 -exec ls -la {} \;

9.2 使用while read循环逐行处理

# 逐个处理失败IP(例如:生成封禁列表)
grep "Failed password" /var/log/auth.log | \
  awk '{print $(NF-3)}' | sort -u | \
  while read ip; do
    count=$(grep -c "$ip" /var/log/auth.log)
    echo "$ip: $count attempts"
  done

# 特定错误模式出现时发出警报
tail -f /var/log/syslog | while read line; do
    echo "$line" | grep -q "CRITICAL" && echo "ALERT: $line" >> /tmp/alerts.log
done

9.3 结合date命令进行时间分析

# 仅提取最近1小时的日志(syslog格式)
SINCE=$(date -d '1 hour ago' '+%b %e %H')
awk -v since="$SINCE" '$0 >= since' /var/log/syslog

# 搜索昨天的日志
YESTERDAY=$(date -d yesterday '+%b %e')
grep "^$YESTERDAY" /var/log/syslog

# 按分钟统计请求数趋势(最近1小时)
awk '{print substr($4,14,5)}' /var/log/nginx/access.log | sort | uniq -c | tail -60

9.4 实战常用单行命令精选

# === 安全分析 ===

# 1. SSH暴力攻击IP Top 10 + 无GeoIP频率分析
grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -10

# 2. 当前活跃的SSH会话
who | grep pts
ss -tnp | grep :22

# 3. sudo命令使用历史
grep "COMMAND" /var/log/auth.log | awk -F: '{print $NF}' | sort | uniq -c | sort -rn | head -20

# 4. 异常端口连接尝试
grep "refused connect" /var/log/syslog | awk '{print $NF}' | sort | uniq -c | sort -rn


# === 性能分析 ===

# 5. Nginx响应码分布
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

# 6. 按时段统计流量(每小时)
awk '{split($4,a,":"); print a[2]":00"}' /var/log/nginx/access.log | sort | uniq -c

# 7. 生成最大响应的URL
awk '{print $10, $7}' /var/log/nginx/access.log | sort -rn | head -20

# 8. 带宽使用量计算(按日)
awk '{sum+=$10} END {printf "%.2f GB\n", sum/1024/1024/1024}' /var/log/nginx/access.log


# === 故障分析 ===

# 9. 最近错误日志综合(去重,按频率排序)
grep -i "error\|fail\|critical\|fatal" /var/log/syslog | \
  sed 's/^.*\] //' | sort | uniq -c | sort -rn | head -30

# 10. 按服务统计重启频率
journalctl --since "7 days ago" | grep "Started" | \
  awk '{for(i=5;i<=NF;i++) printf $i" "; print ""}' | sort | uniq -c | sort -rn | head -20

# 11. 内核panic/OOPS检查
journalctl -k -p crit --since "7 days ago"
dmesg -T | grep -i "panic\|oops\|bug\|error"

# 12. 磁盘满警告相关日志
grep -i "no space\|disk full\|ENOSPC" /var/log/syslog

10. 日志监控自动化

10.1 简单的日志监控脚本

#!/bin/bash
# log_monitor.sh - 日志监控与告警脚本

LOG_FILE="/var/log/syslog"
ALERT_PATTERNS="error|critical|fatal|panic|OOM|segfault"
ALERT_LOG="/var/log/alert_monitor.log"
CHECK_INTERVAL=60

echo "[$(date)] Log monitor started for $LOG_FILE" | tee -a "$ALERT_LOG"

tail -Fn0 "$LOG_FILE" | while read line; do
    if echo "$line" | grep -qiE "$ALERT_PATTERNS"; then
        TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
        echo "[$TIMESTAMP] ALERT: $line" | tee -a "$ALERT_LOG"

        # 在此处添加告警(邮件、Slack等)
        # echo "$line" | mail -s "Log Alert" admin@example.com
    fi
done

10.2 使用logwatch生成每日报告

# 安装logwatch
sudo apt install logwatch          # Debian/Ubuntu
sudo yum install logwatch          # RHEL/CentOS

# 生成每日报告
logwatch --detail High --range today --output stdout

# 通过邮件发送
logwatch --detail High --range yesterday --mailto admin@example.com --format html

# 仅分析特定服务
logwatch --service sshd --detail High --range today

10.3 multitail - 多日志实时监控

# 安装multitail
sudo apt install multitail

# 同时监控多个日志(分屏显示)
multitail /var/log/syslog /var/log/auth.log

# 颜色高亮 + 过滤
multitail -ci green /var/log/nginx/access.log -ci red /var/log/nginx/error.log

# 应用颜色方案和过滤器
multitail -e "error" /var/log/syslog -e "Failed" /var/log/auth.log

10.4 lnav - 结构化日志分析器

# 安装lnav
sudo apt install lnav

# 基本使用(自动格式检测)
lnav /var/log/syslog

# 同时分析多个文件
lnav /var/log/syslog /var/log/auth.log

# 在lnav内部使用SQL查询
# ;SELECT log_time, log_body FROM syslog_log WHERE log_body LIKE '%error%' LIMIT 20

# 自动支持压缩文件
lnav /var/log/syslog.*.gz
TIP: lnav能够自动检测日志格式,并支持颜色区分、时间线、直方图和SQL查询等功能,是一款功能非常强大的基于终端的日志分析器。当需要在终端长时间分析日志时,它是最佳选择。

11. 日志分析最佳实践

11.1 高效的日志分析习惯

  • 从全局视角开始:先用wc -l了解规模 -> 用grep -c确认错误频率 -> 再进行详细分析
  • 缩小时间范围:以故障发生时间点前后为范围缩小分析范围,可以减少不必要的噪音。
  • 逐步构建管道:不要一次性编写复杂的单行命令,而是逐步添加管道并确认结果。
  • 善用alias:将常用的日志分析命令在~/.bashrc中注册为alias,可以提高效率。
  • 用tee保存中间结果:使用command | tee /tmp/result.txt | next_command可以在将中间结果保存到文件的同时继续管道处理。

11.2 实用的bash alias设置

# 添加到~/.bashrc的日志分析alias
alias syslog='tail -f /var/log/syslog'
alias authlog='tail -f /var/log/auth.log'
alias nginxlog='tail -f /var/log/nginx/access.log'
alias nginxerr='tail -f /var/log/nginx/error.log'

alias logerror='grep -i "error\|fail\|critical" /var/log/syslog | tail -50'
alias sshfail='grep "Failed password" /var/log/auth.log | awk '\''{print $(NF-3)}'\'' | sort | uniq -c | sort -rn | head -20'
alias topip='awk '\''{print $1}'\'' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20'

alias jlog='journalctl -f'
alias jerr='journalctl -p err --since "1 hour ago" --no-pager'

11.3 安全注意事项

  • 日志文件权限管理:日志文件可能包含敏感信息(IP、用户名、查询参数),请设置适当的权限(640或更低)。
  • 日志完整性保护:入侵者可能会删除/篡改日志,因此重要服务器应同时采用远程日志收集(rsyslog远程转发、ELK、Loki等)
  • 日志保留策略:考虑法律要求和磁盘容量,适当配置logrotate和保留期限。
  • 个人信息注意:日志中包含的个人信息(IP、邮箱等)必须按照相关隐私法规进行妥善管理。

12. 命令快速参考速查表

用途 命令
实时监控 tail -f /var/log/syslog
关键词实时过滤 tail -f /var/log/syslog | grep --line-buffered "error"
错误计数 grep -ci "error" /var/log/syslog
错误上下文 grep -C 5 "error" /var/log/syslog
按IP统计访问次数 awk '{print $1}' access.log | sort | uniq -c | sort -rn
HTTP状态码分布 awk '{print $9}' access.log | sort | uniq -c | sort -rn
SSH攻击IP grep "Failed password" auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn
按时段统计错误 grep "error" syslog | awk '{print $3}' | cut -d: -f1 | sort | uniq -c
服务日志 journalctl -u nginx.service -p err --since "1h ago"
内核错误 journalctl -k -p err
OOM检查 dmesg -T | grep -i "oom\|killed process"
磁盘错误 grep -i "I/O error\|read-only" /var/log/syslog
压缩日志搜索 zgrep "error" /var/log/syslog.*.gz
日志行数 wc -l /var/log/syslog
日志磁盘使用量 journalctl --disk-usage

总结:日志分析的关键在于实战经验

Linux日志分析仅仅了解工具和命令是不够的。在实际故障场景中,先检查哪个日志文件、用什么模式进行过滤、如何解读结果——这种实战经验才是最重要的。

请在自己的服务器环境中亲自运行本指南中介绍的命令。grepawk的组合、journalctl的各种过滤选项、sort | uniq -c | sort -rn管道,一旦熟练掌握,在任何日志分析场景中都能快速应对。

尤其需要牢记的核心原则如下:

  • 始终从缩小时间范围开始 - 不要翻查整个日志,而是集中在故障发生时间点前后。
  • 逐步构建管道 - 每添加一步都确认结果后再继续。
  • 常用命令保存为alias - 在紧急情况下,使用alias比回忆命令更快。
  • 同步使用远程日志收集 - 仅依赖本地日志无法保障安全性和可用性。
  • 定期检查日志 - 不要等到故障发生后才查看日志,养成平时也监控日志趋势的习惯非常重要。

日志分析能力对于系统管理员、DevOps工程师、SRE和安全工程师来说都是必不可少的核心能力。请立即在终端中运行今天学到的命令,建立属于自己的分析工作流程。