本文目录导读:

要用脚本自动分析Apache错误日志,通常可以结合Shell (awk, grep, sort)、Python 或 Go 来实现,下面我会从最常见的场景(统计错误类型、高频IP、404请求)到更专业的风控/监控给出几种实用的脚本方法。
通用的Shell脚本(快速分析)
适用于Linux/Mac的终端,直接运行即可。
示例:分析 /var/log/apache2/error.log
#!/bin/bash LOG_FILE="/var/log/apache2/error.log" echo "========== Apache 错误日志分析 ==========" # 1. 错误级别统计([error], [warn], [notice]) echo "" echo "--- 错误级别分布 ---" grep -oP '\[\K[^\]]+' "$LOG_FILE" | sort | uniq -c | sort -rn # 2. 出现最多的IP地址(如果日志包含IP) echo "" echo "--- 高频错误来源IP ---" grep -oP 'client \K[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' "$LOG_FILE" | sort | uniq -c | sort -rn | head -20 # 3. 最常见的错误消息(去掉时间前缀后) echo "" echo "--- 高频错误消息 (Top 20) ---" grep -oP '\[.*?\] \[.*?\] \[.*?\] \K.*' "$LOG_FILE" | sort | uniq -c | sort -rn | head -20 # 4. 统计404错误相关(假如日志里记录) echo "" echo "--- 404错误统计 ---" grep "File does not exist" "$LOG_FILE" | wc -l
运行方法
chmod +x analyze_apache_error.sh && ./analyze_apache_error.sh
优点:零依赖,快速上手。
缺点:不擅长复杂的模式匹配和告警。
Python脚本(可扩展,适合定期执行)
Python适合写更复杂的分析逻辑,比如按时间聚合、发送邮件告警、生成图表。
#!/usr/bin/env python3
import re
import sys
from collections import Counter
from datetime import datetime
LOG_FILE = "/var/log/apache2/error.log"
def parse_apache_error_line(line):
"""解析典型的Apache error日志行"""
# 示例行: [Mon Oct 10 12:00:00.123456 2024] [php:notice] [pid 12345] [client 192.168.1.1:51234] File not found
pattern = r'\[([^\]]+)\]' # 提取所有中括号内容
matches = re.findall(pattern, line)
if len(matches) < 3:
return None
# 第一个是时间戳,第二个是模块:级别,后面是pid等
timestamp_str = matches[0]
level_module = matches[1] # "php:notice"
# 尝试解析标准Apache时间格式
try:
# 去除微秒部分
ts_clean = re.sub(r'\..*', '', timestamp_str)
dt = datetime.strptime(ts_clean, '%a %b %d %H:%M:%S %Y')
except:
dt = None
# 提取消息部分(最后一个中括号之后)
msg_start = line.rfind(']') + 1
message = line[msg_start:].strip()
# 提取client IP
client_ip = None
ip_match = re.search(r'client (\d+\.\d+\.\d+\.\d+)', line)
if ip_match:
client_ip = ip_match.group(1)
return {
'time': dt,
'level': level_module,
'client_ip': client_ip,
'message': message
}
def analyze_log(filepath):
errors = []
with open(filepath, 'r', errors='ignore') as f:
for line in f:
parsed = parse_apache_error_line(line)
if parsed:
errors.append(parsed)
print(f"总错误行数: {len(errors)}")
# 按错误级别统计
level_counter = Counter(e['level'] for e in errors)
print("\n--- 错误级别分布 ---")
for level, count in level_counter.most_common():
print(f"{level}: {count}")
# 按IP统计
ip_counter = Counter(e['client_ip'] for e in errors if e['client_ip'])
print("\n--- 高频IP (Top 20) ---")
for ip, count in ip_counter.most_common(20):
print(f"{ip}: {count}")
# 按消息聚合(忽略动态PID等信息)
msg_counter = Counter(e['message'] for e in errors)
print("\n--- 高频消息 (Top 20) ---")
for msg, count in msg_counter.most_common(20):
print(f"{count}x {msg[:100]}")
if __name__ == "__main__":
log_path = sys.argv[1] if len(sys.argv) > 1 else LOG_FILE
analyze_log(log_path)
运行:python3 analyze_apache_error.py /var/log/apache2/error.log
实时监控 + 告警(使用 tail -f + 分析脚本)
适合生产环境:实时读取日志,当特定错误出现(如PHP Fatal Error、连接超时)时自动发邮件或推送到企业微信。
#!/usr/bin/env python3
import time
import re
import smtplib
from collections import deque
ALERT_THRESHOLD = 10 # 10次相同错误触发告警
WATCH_KEYWORDS = ['PHP Fatal error', 'Out of memory', 'Connection refused']
def send_alert(message):
# 示例:发送邮件(需配置SMTP)
# 实际代码可替换为 webhook 或钉钉机器人
print(f"[ALERT] {message}")
def monitor_log(filepath, interval=5):
"""每5秒检查新增日志行"""
with open(filepath, 'r') as f:
# 跳到文件末尾
f.seek(0, 2)
error_window = deque(maxlen=100) # 保存最近100条
while True:
line = f.readline()
if not line:
time.sleep(interval)
continue
# 检查是否包含敏感关键字
for keyword in WATCH_KEYWORDS:
if keyword in line:
print(f"检测到严重错误: {line.strip()}")
send_alert(line)
error_window.append(line.strip())
# 简单统计:最近100行中同一错误次数
if len(error_window) == 100:
counter = {}
for e in error_window:
# 取消息部分作为key
msg = e.split(']')[-1] if ']' in e else e
counter[msg] = counter.get(msg, 0) + 1
# 阈值告警
for msg, cnt in counter.items():
if cnt >= ALERT_THRESHOLD:
send_alert(f"高频错误: {msg} 出现{cnt}次/最近100行")
if __name__ == "__main__":
monitor_log('/var/log/apache2/error.log')
进阶:使用正则提取结构化字段并存入数据库(适合大数据)
如果日志量极大,建议:
- 使用
logstash+elasticsearch或商业化Splunk。 - 自己写脚本将解析后的JSON字段写入
SQLite或PostgreSQL,然后使用SQL进行灵活分析。
关键注意事项
| 场景 | 建议方案 |
|---|---|
| 临时排错 | Shell + grep/awk |
| 定期巡检/报告 | Python脚本 + cron |
| 实时告警 | Python tail + webhook 或 Sentry |
| 大规模分析 | ELK / Loki / Grafana |
额外提示:
- 如果日志格式是自定义的(比如加了虚拟主机名),需要调整正则表达式。
- 当心 IP伪造:日志中的client IP也可能是反向代理IP(如Nginx),需要看
X-Forwarded-For是否被记录。 - 不要在生产环境用
tail -f阻塞脚本可能导致资源泄漏,建议用asyncio或logging.handlers.RotatingFileHandler读取。
如果你能提供具体的日志格式示例或想分析的目标(统计某时刻段错误数、找出导致503的URL),我可以帮你定制更精准的脚本。