日志统计与分析指南
目录
- 1. 多文件查找
- 2. 查找日志的常用方法
- 3. 统计日志内容
- 4. 高级功能
- 5. 实用脚本示例
1. 多文件查找
1.1 查找普通日志文件(.log)
# 查找当前目录及子目录下所有 .log 文件find.-name"*.log"# 查找指定目录下的 .log 文件find/var/log -name"*.log"# 查找最近修改的日志文件find.-name"*.log"-mtime -1# 最近1天find.-name"*.log"-mtime -7# 最近7天
1.2 查找压缩日志文件
# 查找 .gz 压缩文件find.-name"*.log.gz"find.-name"*.gz"# 查找 .zip 压缩文件find.-name"*.log.zip"find.-name"*.zip"# 查找多种压缩格式find.\(-name"*.log.gz"-o -name"*.log.zip"-o -name"*.log.bz2"\)# 查找所有压缩文件(包括 .gz, .zip, .bz2, .xz)find.-type f\(-name"*.gz"-o -name"*.zip"-o -name"*.bz2"-o -name"*.xz"\)
1.3 同时查找普通和压缩日志文件
# 方法1:使用 -o 选项find.\(-name"*.log"-o -name"*.log.gz"-o -name"*.log.zip"\)# 方法2:使用正则表达式(需要 -regex 选项)find.-regex".*\.log\(\.gz\|\.zip\)\?$"# 方法3:分别查找后合并find.-name"*.log"-o -name"*.log.*"|grep-E"\.(log|gz|zip|bz2)$"
1.4 按时间范围查找日志文件
# 查找今天修改的文件find.-name"*.log*"-mtime0# 查找最近3天的文件find.-name"*.log*"-mtime -3# 查找指定日期范围的文件(需要结合 stat 或 ls)find.-name"*.log*"-newermt"2025-01-01"!-newermt"2025-01-31"
2. 查找日志的常用方法
2.1 grep - 最常用的文本搜索工具
grep 常用选项表格
| 选项 | 说明 | 示例 |
|---|
-i | 忽略大小写 | grep -i "error" app.log |
-n | 显示匹配行的行号 | grep -n "ERROR" app.log |
-v | 反向匹配,显示不包含关键字的行 | grep -v "INFO" app.log |
-c | 统计匹配的行数 | grep -c "ERROR" app.log |
-l | 只显示匹配的文件名 | grep -l "ERROR" *.log |
-L | 只显示不匹配的文件名 | grep -L "ERROR" *.log |
-r或-R | 递归搜索目录 | grep -r "ERROR" /var/log/ |
-E | 使用扩展正则表达式 | grep -E "ERROR|WARN" app.log |
-F | 将模式视为固定字符串(不使用正则) | grep -F "ERROR" app.log |
-A n | 显示匹配行及其后 n 行 | grep -A 3 "ERROR" app.log |
-B n | 显示匹配行及其前 n 行 | grep -B 3 "ERROR" app.log |
-C n | 显示匹配行及其前后各 n 行 | grep -C 3 "ERROR" app.log |
-o | 只显示匹配的部分,而不是整行 | grep -o "ERROR" app.log |
-h | 不显示文件名前缀(多文件搜索时) | grep -h "ERROR" *.log |
-H | 显示文件名前缀(默认行为) | grep -H "ERROR" app.log |
-w | 匹配整个单词 | grep -w "error" app.log |
-x | 匹配整行 | grep -x "ERROR" app.log |
-q | 静默模式,不输出结果(用于脚本判断) | grep -q "ERROR" app.log && echo "Found" |
-s | 抑制错误消息 | grep -s "ERROR" app.log |
--color | 高亮显示匹配的文本 | grep --color=always "ERROR" app.log |
-m n | 最多匹配 n 行后停止 | grep -m 10 "ERROR" app.log |
-f file | 从文件中读取模式 | grep -f patterns.txt app.log |
-e pattern | 指定多个模式 | grep -e "ERROR" -e "WARN" app.log |
使用示例
# 基本搜索grep"ERROR"app.log# 忽略大小写grep-i"error"app.log# 显示行号grep-n"ERROR"app.log# 显示匹配行的上下文(前后各3行)grep-C3"ERROR"app.loggrep-B3"ERROR"app.log# 只显示前3行grep-A3"ERROR"app.log# 只显示后3行# 反向匹配(显示不包含关键字的行)grep-v"INFO"app.log# 使用正则表达式grep-E"ERROR|WARN"app.loggrep-E"[0-9]{4}-[0-9]{2}-[0-9]{2}"app.log# 匹配日期格式# 在多个文件中搜索grep"ERROR"*.loggrep-r"ERROR"/var/log/# 递归搜索目录# 只显示匹配的文件名grep-l"ERROR"*.log# 统计匹配的行数grep-c"ERROR"app.log# 只显示匹配的部分grep-o"ERROR"app.log|wc-l# 统计关键字出现次数# 匹配整个单词grep-w"error"app.log# 不会匹配 "errors" 或 "ErrorCode"# 高亮显示匹配文本grep--color=always"ERROR"app.log# 组合使用多个选项grep-rn --color=always"ERROR"/var/log/# 递归搜索、显示行号、高亮显示
2.2 在压缩文件中搜索
# 在 .gz 文件中搜索(zcat 或 zgrep)zgrep"ERROR"app.log.gz zcat app.log.gz|grep"ERROR"# 在 .bz2 文件中搜索bzgrep"ERROR"app.log.bz2 bzcat app.log.bz2|grep"ERROR"# 在 .xz 文件中搜索xzgrep"ERROR"app.log.xz xzcat app.log.xz|grep"ERROR"# 在 .zip 文件中搜索unzip-p app.log.zip|grep"ERROR"# 在多个压缩文件中搜索zgrep"ERROR"*.log.gz
2.3 多文件同时搜索
# 在多个普通日志文件中搜索grep"ERROR"app.log app2.log app3.log# 在普通文件和压缩文件中同时搜索grep"ERROR"*.log&&zgrep"ERROR"*.log.gz# 使用 find + xargs 在多个文件中搜索find.-name"*.log*"-type f|xargsgrep"ERROR"# 处理包含空格的文件名find.-name"*.log*"-type f -print0|xargs-0grep"ERROR"
2.4 按时间范围搜索
# 搜索指定时间段的日志(假设日志格式包含时间戳)grep"2025-01-15"app.log|grep"ERROR"# 搜索时间范围(需要日志格式支持)awk'/2025-01-15 10:00:00/,/2025-01-15 11:00:00/'app.log# 使用 sed 提取时间范围sed-n'/2025-01-15 10:00:00/,/2025-01-15 11:00:00/p'app.log
2.5 高级搜索技巧
# 组合多个条件(AND)grep"ERROR"app.log|grep"PmsService"# 组合多个条件(OR)grep-E"ERROR|WARN|FATAL"app.log# 排除某些行grep"ERROR"app.log|grep-v"DEBUG"# 使用管道链catapp.log|grep"ERROR"|grep"PmsService"|head-20# 实时监控日志(tail + grep)tail-f app.log|grep"ERROR"
3. 统计日志内容
3.1 统计行数
# 统计文件总行数wc-l app.log# 统计多个文件的行数wc-l *.log# 统计匹配关键字的行数grep-c"ERROR"app.log# 统计多个文件中匹配的行数grep-c"ERROR"*.log# 统计压缩文件的行数zcat app.log.gz|wc-l
3.2 统计关键字出现次数
# 统计单个关键字出现次数grep-o"ERROR"app.log|wc-l# 统计多个关键字出现次数grep-oE"ERROR|WARN|FATAL"app.log|sort|uniq-c# 统计每个关键字的出现次数并排序grep-oE"ERROR|WARN|FATAL"app.log|sort|uniq-c|sort-rn# 统计所有唯一关键字的出现次数grep-oE"ERROR|WARN|FATAL"app.log|sort|uniq-c
3.3 统计关键字频率(Top N)
# 统计出现频率最高的10个关键字grep-oE"ERROR|WARN|FATAL"app.log|sort|uniq-c|sort-rn|head-10# 统计所有单词的频率(Top 20)catapp.log|tr-s' ''\n'|sort|uniq-c|sort-rn|head-20# 统计特定模式的频率(如类名、方法名)grep-oE"\[PmsService\]|\[CouponService\]"app.log|sort|uniq-c|sort-rn
3.4 按时间统计
# 统计每小时错误数量(假设日志格式:yyyy-MM-dd HH:mm:ss)grep"ERROR"app.log|awk'{print$1" "$2}'|cut-d: -f1|sort|uniq-c# 统计每天的日志行数awk'{print$1}'app.log|sort|uniq-c# 统计每分钟的请求数(需要根据实际日志格式调整)awk'{print substr($0,1,16)}'app.log|sort|uniq-c
3.5 统计文件大小
# 查看文件大小ls-lh app.log# 查看多个文件的总大小du-ch *.log# 查看压缩文件大小ls-lh *.log.gz# 查看目录下所有日志文件的总大小du-sh /var/log/
3.6 统计唯一值
# 统计唯一的错误类型grep"ERROR"app.log|awk-F'ERROR''{print$2}'|sort|uniq# 统计唯一的用户ID(假设日志中包含用户ID)grep-oE"userId:[0-9]+"app.log|sort|uniq# 统计唯一的IP地址grep-oE"[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"app.log|sort|uniq
4. 高级功能
4.1 日志聚合分析
# 合并多个日志文件并排序cat*.log|sort# 合并并去重cat*.log|sort|uniq# 合并压缩文件zcat *.log.gz|sort
4.2 提取特定字段
# 使用 awk 提取特定列awk'{print$1,$2,$5}'app.log# 提取第1、2、5列# 提取 JSON 格式日志中的特定字段(需要 jq)catapp.log|jq'.level, .message'# 提取时间戳和错误信息grep"ERROR"app.log|awk'{print$1" "$2" "$NF}'
4.3 日志格式化输出
# 美化 JSON 日志(需要 jq)catapp.log|jq'.'# 格式化时间戳awk'{print strftime("%Y-%m-%d %H:%M:%S",$1)}'app.log# 添加行号cat-n app.log
4.4 日志对比分析
# 对比两个日志文件的差异diffapp.log app2.log# 对比并显示上下文diff-u app.log app2.log# 找出只在文件1中存在的行comm-23<(sortapp.log)<(sortapp2.log)# 找出两个文件共有的行comm-12<(sortapp.log)<(sortapp2.log)
4.5 性能分析
# 统计接口响应时间(假设日志包含耗时信息)grep-oE"耗时 [0-9]+ ms"app.log|grep-oE"[0-9]+"|awk'{sum+=$1; count++} END {print "平均耗时:", sum/count, "ms"}'# 找出最慢的10个请求grep-oE"耗时 [0-9]+ ms"app.log|grep-oE"[0-9]+"|sort-rn|head-10# 统计耗时分布grep-oE"耗时 [0-9]+ ms"app.log|grep-oE"[0-9]+"|awk'{if($1<100) a++; else if($1<500) b++; else c++} END {print "0-100ms:", a, "100-500ms:", b, ">500ms:", c}'
4.6 错误分析
# 提取错误堆栈awk'/ERROR/,/^[[:space:]]*$/'app.log# 统计异常类型grep-oE"Exception: [a-zA-Z.]+"app.log|sort|uniq-c|sort-rn# 找出最常见的错误消息grep"ERROR"app.log|awk-F'ERROR''{print$2}'|sort|uniq-c|sort-rn|head-10
4.7 实时监控
# 实时监控日志文件tail-f app.log# 实时监控并过滤tail-f app.log|grep"ERROR"# 监控多个日志文件tail-f app.log app2.log# 实时监控并高亮关键字tail-f app.log|grep--color=always -E"ERROR|WARN|FATAL"
4.8 日志采样
# 每10行采样1行awk'NR % 10 == 0'app.log# 随机采样1000行shuf-n1000app.log# 采样前1000行和后1000行head-1000 app.log&&tail-1000 app.log
5. 实用脚本示例
5.1 统计所有日志文件中的错误数量
#!/bin/bash# 统计所有日志文件(包括压缩文件)中的错误数量LOG_DIR="/var/log"KEYWORD="ERROR"echo"正在统计$LOG_DIR目录下的错误日志..."# 统计普通日志文件forfilein$(find$LOG_DIR -name"*.log"-type f);docount=$(grep-c"$KEYWORD""$file"2>/dev/null||echo"0")echo"$file:$count"done# 统计压缩日志文件forfilein$(find$LOG_DIR -name"*.log.gz"-type f);docount=$(zgrep -c"$KEYWORD""$file"2>/dev/null||echo"0")echo"$file:$count"done
5.2 按日期统计日志
#!/bin/bash# 按日期统计日志行数LOG_FILE="app.log"echo"日期统计:"awk'{print$1}'$LOG_FILE|sort|uniq-c|sort-rn
5.3 提取错误日志到单独文件
#!/bin/bash# 从多个日志文件中提取错误日志OUTPUT_FILE="errors.log"KEYWORD="ERROR">$OUTPUT_FILE# 清空输出文件# 处理普通日志文件forfilein*.log;doif[-f"$file"];thenecho"处理文件:$file"grep"$KEYWORD""$file">>$OUTPUT_FILEfidone# 处理压缩日志文件forfilein*.log.gz;doif[-f"$file"];thenecho"处理文件:$file"zgrep"$KEYWORD""$file">>$OUTPUT_FILEfidoneecho"错误日志已保存到:$OUTPUT_FILE"
5.4 分析日志中的慢请求
#!/bin/bash# 分析日志中的慢请求(假设日志包含耗时信息)LOG_FILE="app.log"THRESHOLD=1000# 阈值:1000msecho"查找耗时超过${THRESHOLD}ms 的请求:"grep-E"耗时 [0-9]+ ms"$LOG_FILE|\grep-oE"耗时 [0-9]+ ms"|\grep-oE"[0-9]+"|\awk-vthreshold=$THRESHOLD'$1> threshold {print$1" ms"}'|\sort-rn|head-20
5.5 统计日志文件大小和行数
#!/bin/bash# 统计所有日志文件的大小和行数echo"文件大小 | 行数 | 文件名"echo"----------------------------------------"forfilein$(find.-name"*.log*"-type f);doif[[$file==*.gz]];thensize=$(du-h"$file"|cut-f1)lines=$(zcat"$file"2>/dev/null|wc-l)elif[[$file==*.bz2]];thensize=$(du-h"$file"|cut-f1)lines=$(bzcat"$file"2>/dev/null|wc-l)elsesize=$(du-h"$file"|cut-f1)lines=$(wc-l<"$file")fiprintf"%-10s | %-8s | %s\n""$size""$lines""$file"done
5.6 一键日志分析报告
#!/bin/bash# 生成日志分析报告LOG_FILE="${1:-app.log}"REPORT_FILE="log_report_$(date+%Y%m%d_%H%M%S).txt"{echo"========================================="echo"日志分析报告"echo"生成时间:$(date)"echo"日志文件:$LOG_FILE"echo"========================================="echo""echo"1. 基本信息"echo"----------------------------------------"echo"总行数:$(wc-l<$LOG_FILE)"echo"文件大小:$(du-h $LOG_FILE|cut-f1)"echo""echo"2. 错误统计"echo"----------------------------------------"echo"ERROR 数量:$(grep-c"ERROR"$LOG_FILE2>/dev/null||echo"0")"echo"WARN 数量:$(grep-c"WARN"$LOG_FILE2>/dev/null||echo"0")"echo"FATAL 数量:$(grep-c"FATAL"$LOG_FILE2>/dev/null||echo"0")"echo""echo"3. Top 10 错误消息"echo"----------------------------------------"grep"ERROR"$LOG_FILE|awk-F'ERROR''{print$2}'|sort|uniq-c|sort-rn|head-10echo""echo"4. 时间分布(按小时)"echo"----------------------------------------"awk'{print$2}'$LOG_FILE|cut-d: -f1|sort|uniq-cecho""}>$REPORT_FILEecho"报告已生成:$REPORT_FILE"cat$REPORT_FILE
5.7 使用说明
# 给脚本添加执行权限chmod+x script_name.sh# 运行脚本./script_name.sh# 或者直接使用 bash 运行bashscript_name.sh
6. 常用工具推荐
6.1 命令行工具
- grep: 文本搜索(已内置)
- awk: 文本处理(已内置)
- sed: 流编辑器(已内置)
- jq: JSON 处理工具(需要安装)
- rg (ripgrep): 更快的 grep 替代品(需要安装)
- ag (The Silver Searcher): 代码搜索工具(需要安装)
6.2 安装额外工具
# macOSbrewinstalljq ripgrep the_silver_searcher# Ubuntu/Debiansudoapt-getinstalljq ripgrep silversearcher-ag# CentOS/RHELsudoyuminstalljq epel-releasesudoyuminstallripgrep the_silver_searcher
6.3 使用 ripgrep (rg) 的优势
# rg 比 grep 更快,且默认递归搜索rg"ERROR".# 递归搜索当前目录rg"ERROR"--type log# 只搜索日志文件rg"ERROR"-g"*.log"# 使用 glob 模式rg"ERROR"-g"*.log.gz"# 搜索压缩文件(需要配合其他工具)
7. 最佳实践
7.1 日志文件管理
- 定期清理旧日志文件
- 使用日志轮转(logrotate)
- 压缩历史日志以节省空间
- 设置日志保留策略
7.2 搜索优化
- 使用
grep -E进行正则匹配时,尽量使用具体模式 - 大文件搜索时,先使用
head或tail缩小范围 - 压缩文件搜索时,优先使用
zgrep等专用工具
7.3 性能考虑
- 大文件处理时,考虑使用
split分割文件 - 使用
parallel工具并行处理多个文件 - 对于超大数据集,考虑使用专门的日志分析工具(如 ELK Stack)
8. 快速参考
8.1 常用命令速查
| 需求 | 命令 |
|---|
| 查找所有日志文件 | find . -name "*.log*" |
| 搜索关键字 | grep "ERROR" app.log |
| 统计行数 | wc -l app.log |
| 统计关键字数量 | grep -c "ERROR" app.log |
| 实时监控 | tail -f app.log | grep "ERROR" |
| 搜索压缩文件 | zgrep "ERROR" app.log.gz |
| 提取时间范围 | sed -n '/start/,/end/p' app.log |
| 统计频率 | grep -o "ERROR" app.log | sort | uniq -c |
8.2 常用组合命令
# 查找 + 搜索 + 统计find.-name"*.log"-execgrep-c"ERROR"{}\;# 搜索 + 排序 + 去重 + 统计grep"ERROR"app.log|sort|uniq-c|sort-rn# 提取 + 格式化 + 输出grep"ERROR"app.log|awk'{print$1,$2,$NF}'>errors.txt
提示: 根据实际日志格式调整命令中的字段分隔符和模式匹配规则。