Apache 日志管理 #

日志概述 #

Apache 日志类型 #

text
┌─────────────────────────────────────────────────────────────┐
│                    Apache 日志类型                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  访问日志 (Access Log)                                      │
│  ├── 记录所有 HTTP 请求                                     │
│  ├── 包含客户端信息、请求内容、响应状态                     │
│  └── 用于流量分析、安全审计                                 │
│                                                             │
│  错误日志 (Error Log)                                       │
│  ├── 记录服务器错误和警告                                   │
│  ├── 包含配置错误、脚本错误、系统问题                       │
│  └── 用于故障排查、问题诊断                                 │
│                                                             │
│  日志位置:                                                 │
│  Ubuntu/Debian:                                             │
│  /var/log/apache2/access.log                                │
│  /var/log/apache2/error.log                                 │
│                                                             │
│  CentOS/RHEL:                                               │
│  /var/log/httpd/access_log                                  │
│  /var/log/httpd/error_log                                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

错误日志配置 #

基本配置 #

apache
# ============================================
# 错误日志配置
# ============================================

# 错误日志位置
ErrorLog ${APACHE_LOG_DIR}/error.log

# 日志级别
LogLevel warn

# 日志级别说明(从低到高)
# emerg   - 紧急情况,系统不可用
# alert   - 必须立即处理
# crit    - 严重情况
# error   - 错误
# warn    - 警告
# notice  - 正常但重要的情况
# info    - 信息
# debug   - 调试信息
# trace1-8 - 详细跟踪信息

虚拟主机错误日志 #

apache
# ============================================
# 虚拟主机独立错误日志
# ============================================

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /var/www/example
    
    # 独立错误日志
    ErrorLog ${APACHE_LOG_DIR}/example-error.log
    
    # 日志级别
    LogLevel warn
    
    # 可以针对不同模块设置不同级别
    LogLevel warn core:info ssl:warn
</VirtualHost>

模块级别日志 #

apache
# ============================================
# 模块级别日志配置
# ============================================

# 全局配置
LogLevel warn

# 特定模块日志级别
LogLevel warn ssl:info
LogLevel warn core:error
LogLevel warn mod_rewrite:trace3

# 调试 rewrite
LogLevel alert rewrite:trace6

# 调试 SSL
LogLevel warn ssl_module:debug

访问日志配置 #

日志格式定义 #

apache
# ============================================
# 日志格式定义
# ============================================

# 通用日志格式 (CLF)
LogFormat "%h %l %u %t \"%r\" %>s %b" common

# 组合日志格式(推荐)
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

# 虚拟主机格式
LogFormat "%v:%p %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined

# 自定义格式
LogFormat "%h %l %u %t \"%r\" %>s %b %D \"%{Referer}i\" \"%{User-Agent}i\"" custom

格式说明符 #

text
┌─────────────────────────────────────────────────────────────┐
│                    日志格式说明符                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  连接信息:                                                 │
│  %h      客户端 IP 地址                                     │
│  %l      远程登录名(通常 -)                               │
│  %a      客户端 IP(来自 mod_remoteip)                     │
│  %{c}a   连接客户端 IP                                      │
│                                                             │
│  用户信息:                                                 │
│  %u      认证用户名                                         │
│                                                             │
│  时间信息:                                                 │
│  %t      请求时间 [day/month/year:hour:minute:second zone] │
│  %{format}t  自定义时间格式                                 │
│  %T      处理时间(秒)                                     │
│  %D      处理时间(微秒)                                   │
│                                                             │
│  请求信息:                                                 │
│  %r      请求行(方法 URL 协议)                            │
│  %m      请求方法                                           │
│  %U      请求 URL 路径                                      │
│  %q      查询字符串                                         │
│  %H      请求协议                                           │
│                                                             │
│  响应信息:                                                 │
│  %>s     响应状态码                                         │
│  %b      响应大小(字节),0 显示 -                         │
│  %B      响应大小(字节),0 显示 0                         │
│  %O      发送字节数                                         │
│  %I      接收字节数                                         │
│                                                             │
│  HTTP 头:                                                  │
│  %{Header}i   请求头                                        │
│  %{Header}o   响应头                                        │
│  %{Referer}i  Referer 头                                    │
│  %{User-Agent}i User-Agent 头                               │
│                                                             │
│  其他:                                                     │
│  %v      服务器名称                                         │
│  %V      虚拟主机名称                                       │
│  %p      服务器端口                                         │
│  %P      进程 ID                                            │
│  %{pid}P 进程 ID                                            │
│  %X      连接状态                                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

自定义日志格式 #

apache
# ============================================
# 自定义日志格式
# ============================================

# JSON 格式日志
LogFormat "{ \"time\": \"%{%Y-%m-%d %H:%M:%S}t\", \"remote_ip\": \"%h\", \"request\": \"%r\", \"status\": %>s, \"size\": %b, \"referer\": \"%{Referer}i\", \"user_agent\": \"%{User-Agent}i\", \"duration\": %D }" json

# 详细性能日志
LogFormat "%h %l %u %t \"%r\" %>s %b %D \"%{Referer}i\" \"%{User-Agent}i\" %I %O" performance

# 安全审计日志
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{X-Forwarded-For}i\"" security

# 使用自定义格式
CustomLog ${APACHE_LOG_DIR}/access.json json
CustomLog ${APACHE_LOG_DIR}/performance.log performance

访问日志配置 #

apache
# ============================================
# 访问日志配置
# ============================================

# 使用预定义格式
CustomLog ${APACHE_LOG_DIR}/access.log combined

# 使用自定义格式名
CustomLog ${APACHE_LOG_DIR}/access.log common

# 直接指定格式
CustomLog ${APACHE_LOG_DIR}/access.log "%h %l %u %t \"%r\" %>s %b"

# 条件日志(仅记录 4xx 和 5xx)
SetEnvIf Request_URI "\.gif$" nolog
SetEnvIf Request_URI "\.jpg$" nolog
CustomLog ${APACHE_LOG_DIR}/access.log combined env=!nolog

虚拟主机访问日志 #

apache
# ============================================
# 虚拟主机独立访问日志
# ============================================

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /var/www/example
    
    # 独立访问日志
    CustomLog ${APACHE_LOG_DIR}/example-access.log combined
    
    # 错误日志
    ErrorLog ${APACHE_LOG_DIR}/example-error.log
</VirtualHost>

<VirtualHost *:80>
    ServerName api.example.com
    DocumentRoot /var/www/api
    
    # API 专用日志
    CustomLog ${APACHE_LOG_DIR}/api-access.log combined
    ErrorLog ${APACHE_LOG_DIR}/api-error.log
</VirtualHost>

日志切割与轮转 #

使用 rotatelogs #

apache
# ============================================
# rotatelogs 日志切割
# ============================================

# 按天切割
CustomLog "|/usr/bin/rotatelogs ${APACHE_LOG_DIR}/access-%Y%m%d.log 86400" combined

# 按小时切割
CustomLog "|/usr/bin/rotatelogs ${APACHE_LOG_DIR}/access-%Y%m%d-%H.log 3600" combined

# 按大小切割(5MB)
CustomLog "|/usr/bin/rotatelogs ${APACHE_LOG_DIR}/access-%Y%m%d-%H%M%S.log 5M" combined

# 错误日志切割
ErrorLog "|/usr/bin/rotatelogs ${APACHE_LOG_DIR}/error-%Y%m%d.log 86400"

# 保留最近 7 天
CustomLog "|/usr/bin/rotatelogs ${APACHE_LOG_DIR}/access-%Y%m%d.log 86400" combined

使用 logrotate #

bash
# ============================================
# logrotate 配置
# ============================================

# 配置文件位置
# /etc/logrotate.d/apache2

/var/log/apache2/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 640 www-data adm
    sharedscripts
    postrotate
        if /etc/init.d/apache2 status > /dev/null ; then \
            /etc/init.d/apache2 reload > /dev/null; \
        fi
    endscript
}

# 手动执行
sudo logrotate -f /etc/logrotate.d/apache2

# 测试配置
sudo logrotate -d /etc/logrotate.d/apache2

CentOS/RHEL logrotate #

bash
# ============================================
# CentOS/RHEL logrotate 配置
# ============================================

# /etc/logrotate.d/httpd

/var/log/httpd/*log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 640 apache apache
    sharedscripts
    postrotate
        /bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
    endscript
}

日志分析 #

基本分析命令 #

bash
# ============================================
# 日志分析命令
# ============================================

# 查看最近访问
sudo tail -n 100 /var/log/apache2/access.log

# 实时查看
sudo tail -f /var/log/apache2/access.log

# 统计访问量
sudo wc -l /var/log/apache2/access.log

# 统计各状态码数量
sudo awk '{print $9}' /var/log/apache2/access.log | sort | uniq -c | sort -nr

# 统计访问量前 10 的 IP
sudo awk '{print $1}' /var/log/apache2/access.log | sort | uniq -c | sort -nr | head -10

# 统计访问量前 10 的 URL
sudo awk '{print $7}' /var/log/apache2/access.log | sort | uniq -c | sort -nr | head -10

# 查找特定 IP 的访问
sudo grep "192.168.1.100" /var/log/apache2/access.log

# 查找 404 错误
sudo grep " 404 " /var/log/apache2/access.log

# 查找 500 错误
sudo grep " 500 " /var/log/apache2/access.log

# 统计某天访问量
sudo grep "29/Mar/2026" /var/log/apache2/access.log | wc -l

# 统计某小时访问量
sudo grep "29/Mar/2026:12:" /var/log/apache2/access.log | wc -l

高级分析 #

bash
# ============================================
# 高级日志分析
# ============================================

# 统计请求方法分布
sudo awk '{print $6}' /var/log/apache2/access.log | sort | uniq -c | sort -nr

# 统计响应时间分布
sudo awk '{print $NF}' /var/log/apache2/access.log | sort -n | uniq -c

# 查找慢请求(超过 1 秒)
sudo awk '$NF > 1000000' /var/log/apache2/access.log

# 统计 User-Agent 分布
sudo awk -F'"' '{print $6}' /var/log/apache2/access.log | sort | uniq -c | sort -nr | head -10

# 统计 Referer 分布
sudo awk -F'"' '{print $4}' /var/log/apache2/access.log | sort | uniq -c | sort -nr | head -10

# 查找爬虫请求
sudo grep -i "bot\|crawl\|spider" /var/log/apache2/access.log

# 统计每小时访问量
sudo awk '{print substr($4, 14, 2)}' /var/log/apache2/access.log | sort | uniq -c

# 统计每天访问量
sudo awk '{print substr($4, 2, 11)}' /var/log/apache2/access.log | sort | uniq -c

使用 GoAccess 分析 #

bash
# ============================================
# GoAccess 日志分析工具
# ============================================

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

# 命令行分析
sudo goaccess /var/log/apache2/access.log -o report.html --log-format=COMBINED

# 实时分析
sudo goaccess /var/log/apache2/access.log -o report.html --log-format=COMBINED --real-time-html

# 分析多个日志
sudo goaccess /var/log/apache2/access*.log --log-format=COMBINED

条件日志 #

排除静态资源 #

apache
# ============================================
# 排除静态资源日志
# ============================================

# 标记静态资源
SetEnvIf Request_URI "\.(gif|jpg|jpeg|png|css|js|ico)$" nolog

# 标记本地请求
SetEnvIf Remote_Addr "^127\.0\.0\.1$" nolog

# 使用条件日志
CustomLog ${APACHE_LOG_DIR}/access.log combined env=!nolog

分离日志 #

apache
# ============================================
# 分离不同类型日志
# ============================================

# 标记不同类型请求
SetEnvIf Request_URI "^/api/" api_log
SetEnvIf Request_URI "^/static/" static_log
SetEnvIf Request_URI "^/admin/" admin_log

# 分别记录
CustomLog ${APACHE_LOG_DIR}/api.log combined env=api_log
CustomLog ${APACHE_LOG_DIR}/static.log combined env=static_log
CustomLog ${APACHE_LOG_DIR}/admin.log combined env=admin_log
CustomLog ${APACHE_LOG_DIR}/other.log combined env=!api_log,!static_log,!admin_log

仅记录错误 #

apache
# ============================================
# 仅记录错误响应
# ============================================

# 标记 4xx 和 5xx 响应
SetEnvIf Status "^4" error_log
SetEnvIf Status "^5" error_log

# 仅记录错误
CustomLog ${APACHE_LOG_DIR}/error-access.log combined env=error_log

日志安全 #

日志权限 #

bash
# ============================================
# 日志文件权限
# ============================================

# 设置日志目录权限
sudo chmod 750 /var/log/apache2
sudo chown root:adm /var/log/apache2

# 设置日志文件权限
sudo chmod 640 /var/log/apache2/*.log
sudo chown root:adm /var/log/apache2/*.log

日志脱敏 #

apache
# ============================================
# 日志脱敏配置
# ============================================

# 不记录敏感 URL
SetEnvIf Request_URI "^/login" nolog
SetEnvIf Request_URI "^/password" nolog

# 自定义格式,不记录查询字符串
LogFormat "%h %l %u %t \"%m %U %>s %b\"" combined_no_query
CustomLog ${APACHE_LOG_DIR}/access.log combined_no_query

完整配置示例 #

apache
# ============================================
# 完整日志配置示例
# ============================================

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /var/www/example
    
    # 错误日志
    ErrorLog ${APACHE_LOG_DIR}/example-error.log
    LogLevel warn
    
    # 定义日志格式
    LogFormat "%h %l %u %t \"%r\" %>s %b %D \"%{Referer}i\" \"%{User-Agent}i\"" detailed
    
    # 排除静态资源
    SetEnvIf Request_URI "\.(gif|jpg|jpeg|png|css|js|ico|woff|woff2)$" nolog
    
    # 访问日志(按天切割)
    CustomLog "|/usr/bin/rotatelogs ${APACHE_LOG_DIR}/example-access-%Y%m%d.log 86400" detailed env=!nolog
    
    <Directory /var/www/example>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

下一步 #

掌握了日志管理后,继续学习 缓存配置,了解如何配置 Apache 缓存提升性能!

最后更新:2026-03-29