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