日志统计与分析指南
目录
1. 多文件查找
1.1 查找普通日志文件(.log)
find . -name "*.log"
find /var/log -name "*.log"
find . -name "*.log" -mtime -1
find . -name "*.log" -mtime -7
1.2 查找压缩日志文件
find . -name "*.log.gz"
find . -name "*.gz"
find . -name "*.log.zip"
find . -name "*.zip"
find . \( -name "*.log.gz" -o -name "*.log.zip" -o -name "*.log.bz2" \)
find . -type f \( -name "*.gz" -o -name "*.zip" -o -name "*.bz2" -o -name "*.xz" \)
1.3 同时查找普通和压缩日志文件
find . \( -name "*.log" -o -name "*.log.gz" -o -name "*.log.zip" \)
find . -regex ".*\.log\(\.gz\|\.zip\)\?$"
find . -name "*.log" -o -name "*.log.*" | grep -E "\.(log|gz|zip|bz2)$"
1.4 按时间范围查找日志文件
find . -name "*.log*" -mtime 0
find . -name "*.log*" -mtime -3
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
grep -C 3 "ERROR" app.log
grep -B 3 "ERROR" app.log
grep -A 3 "ERROR" app.log
grep -v "INFO" app.log
grep -E "ERROR|WARN" app.log
grep -E "[0-9]{4}-[0-9]{2}-[0-9]{2}" app.log
grep "ERROR" *.log
grep -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
grep --color=always "ERROR" app.log
grep -rn --color=always "ERROR" /var/log/
2.2 在压缩文件中搜索
zgrep "ERROR" app.log.gz
zcat app.log.gz | grep "ERROR"
bzgrep "ERROR" app.log.bz2
bzcat app.log.bz2 | grep "ERROR"
xzgrep "ERROR" app.log.xz
xzcat app.log.xz | grep "ERROR"
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 . -name "*.log*" -type f | xargs grep "ERROR"
find . -name "*.log*" -type f -print0 | xargs -0 grep "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 -n '/2025-01-15 10:00:00/,/2025-01-15 11:00:00/p' app.log
2.5 高级搜索技巧
grep "ERROR" app.log | grep "PmsService"
grep -E "ERROR|WARN|FATAL" app.log
grep "ERROR" app.log | grep -v "DEBUG"
cat app.log | grep "ERROR" | grep "PmsService" | head -20
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)
grep -oE "ERROR|WARN|FATAL" app.log | sort | uniq -c | sort -rn | head -10
cat app.log | tr -s ' ' '\n' | sort | uniq -c | sort -rn | head -20
grep -oE "\[PmsService\]|\[CouponService\]" app.log | sort | uniq -c | sort -rn
3.4 按时间统计
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
grep -oE "userId:[0-9]+" app.log | sort | uniq
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 '{print $1, $2, $5}' app.log
cat app.log | jq '.level, .message'
grep "ERROR" app.log | awk '{print $1" "$2" "$NF}'
4.3 日志格式化输出
cat app.log | jq '.'
awk '{print strftime("%Y-%m-%d %H:%M:%S", $1)}' app.log
cat -n app.log
4.4 日志对比分析
diff app.log app2.log
diff -u app.log app2.log
comm -23 <(sort app.log) <(sort app2.log)
comm -12 <(sort app.log) <(sort app2.log)
4.5 性能分析
grep -oE "耗时 [0-9]+ ms" app.log | grep -oE "[0-9]+" | awk '{sum+=$1; count++} END {print "平均耗时:", sum/count, "ms"}'
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 日志采样
awk 'NR % 10 == 0' app.log
shuf -n 1000 app.log
head -1000 app.log && tail -1000 app.log
5. 实用脚本示例
5.1 统计所有日志文件中的错误数量
#!/bin/bash
LOG_DIR="/var/log"
KEYWORD="ERROR"
echo "正在统计 $LOG_DIR 目录下的错误日志..."
for file in $(find $LOG_DIR -name "*.log" -type f); do
count=$(grep -c "$KEYWORD" "$file" 2>/dev/null || echo "0")
echo "$file: $count"
done
for file in $(find $LOG_DIR -name "*.log.gz" -type f); do
count=$(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
for file in *.log; do
if [ -f "$file" ]; then
echo "处理文件: $file"
grep "$KEYWORD" "$file" >> $OUTPUT_FILE
fi
done
for file in *.log.gz; do
if [ -f "$file" ]; then
echo "处理文件: $file"
zgrep "$KEYWORD" "$file" >> $OUTPUT_FILE
fi
done
echo "错误日志已保存到: $OUTPUT_FILE"
5.4 分析日志中的慢请求
#!/bin/bash
LOG_FILE="app.log"
THRESHOLD=1000
echo "查找耗时超过 ${THRESHOLD}ms 的请求:"
grep -E "耗时 [0-9]+ ms" $LOG_FILE | \
grep -oE "耗时 [0-9]+ ms" | \
grep -oE "[0-9]+" | \
awk -v threshold=$THRESHOLD '$1 > threshold {print $1" ms"}' | \
sort -rn | head -20
5.5 统计日志文件大小和行数
#!/bin/bash
echo "文件大小 | 行数 | 文件名"
echo "----------------------------------------"
for file in $(find . -name "*.log*" -type f); do
if [[ $file == *.gz ]]; then
size=$(du -h "$file" | cut -f1)
lines=$(zcat "$file" 2>/dev/null | wc -l)
elif [[ $file == *.bz2 ]]; then
size=$(du -h "$file" | cut -f1)
lines=$(bzcat "$file" 2>/dev/null | wc -l)
else
size=$(du -h "$file" | cut -f1)
lines=$(wc -l < "$file")
fi
printf "%-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_FILE 2>/dev/null || echo "0")"
echo "WARN 数量: $(grep -c "WARN" $LOG_FILE 2>/dev/null || echo "0")"
echo "FATAL 数量: $(grep -c "FATAL" $LOG_FILE 2>/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 -10
echo ""
echo "4. 时间分布(按小时)"
echo "----------------------------------------"
awk '{print $2}' $LOG_FILE | cut -d: -f1 | sort | uniq -c
echo ""
} > $REPORT_FILE
echo "报告已生成: $REPORT_FILE"
cat $REPORT_FILE
5.7 使用说明
chmod +x script_name.sh
./script_name.sh
bash script_name.sh
6. 常用工具推荐
6.1 命令行工具
- grep: 文本搜索(已内置)
- awk: 文本处理(已内置)
- sed: 流编辑器(已内置)
- jq: JSON 处理工具(需要安装)
- rg (ripgrep): 更快的 grep 替代品(需要安装)
- ag (The Silver Searcher): 代码搜索工具(需要安装)
6.2 安装额外工具
brew install jq ripgrep the_silver_searcher
sudo apt-get install jq ripgrep silversearcher-ag
sudo yum install jq epel-release
sudo yum install ripgrep the_silver_searcher
6.3 使用 ripgrep (rg) 的优势
rg "ERROR" .
rg "ERROR" --type log
rg "ERROR" -g "*.log"
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" -exec grep -c "ERROR" {} \;
grep "ERROR" app.log | sort | uniq -c | sort -rn
grep "ERROR" app.log | awk '{print $1, $2, $NF}' > errors.txt
提示: 根据实际日志格式调整命令中的字段分隔符和模式匹配规则。