customlog 必须配合 logformat 才能记录 ip 和路径;默认格式含 %h(ip)但 %r 是完整请求行,非纯路径;应使用 %u%q 组合获取干净路径,并注意 ipv6 方括号、代理 ip、日志轮转与权限问题。

CustomLog 指令必须配合 LogFormat 才能记录 IP 和路径
单独写 CustomLog 不会生效,Apache 默认日志格式(%h %l %u %t "%r" %>s %b)里虽含 %h(客户端 IP),但不包含请求路径的完整字段——%r 是整个请求行(如 GET /api/v1/users HTTP/1.1),不是纯路径。要干净提取路径,得自定义 LogFormat。
实操建议:
- 在
httpd.conf或虚拟主机配置中先定义格式:LogFormat "%h %U%q" ip_path
(%h是 IP,%U是不含查询参数的路径,%q是带问号的查询字符串,合起来就是完整请求路径) - 再启用日志:
CustomLog "/var/log/apache2/access_ip_path.log" ip_path
- 重启 Apache:
sudo systemctl reload apache2(Debian/Ubuntu)或sudo apachectl graceful(RHEL/CentOS)
别用 %r 替代 %U%q:它会混入 HTTP 方法和协议版本
如果误写成 LogFormat "%h %r" ip_path,日志会变成类似 192.168.1.5 GET /search?q=test HTTP/1.1,后续用脚本解析路径时得额外切分,容易出错。而 %U%q 输出是干净的 /search?q=test,无协议干扰。
常见错误现象:
- 用
awk '{print $2}'提取路径失败,因为$2可能是GET而非路径 - 日志分析工具(如 GoAccess)无法识别格式,报
Invalid log format - 路径含空格或特殊字符时,
%r中的引号未转义,导致字段错位
IPv6 访问者 IP 会被方括号包裹,需注意日志解析兼容性
当客户端是 IPv6(如 ::1 或 2001:db8::1),%h 输出为 [::1] 或 [2001:db8::1]。这本身没错,但如果你用简单正则(如 ^\d+\.\d+\.\d+\.\d+)只匹配 IPv4,就会漏掉所有 IPv6 请求。
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
使用场景提醒:
- 做访问统计或封禁脚本时,应支持带方括号的 IPv6 格式,例如用
sed 's/^\[\(.*\)\]$/\1/'去括号 - 若用
mod_remoteip或 CDN(如 Cloudflare),%h实际是代理 IP,需改用%{X-Forwarded-For}i并确保RemoteIPHeader已配 -
%h在 HTTPS 且启用了mod_ssl时仍有效,不依赖加密状态
日志文件权限和轮转必须手动配,否则磁盘可能被撑爆
CustomLog 不自动轮转,也不检查磁盘空间。如果流量大、路径又长(比如带大量 utm_* 参数),单条日志可达几 KB,一天就可能生成 GB 级文件。
关键操作:
- 用
rotatelogs内置工具(推荐):CustomLog "|/usr/bin/rotatelogs -l /var/log/apache2/access_ip_path.log 86400" ip_path
(按天轮转,-l用本地时间) - 或配合
logrotate,但需加create 644 www-data www-data确保新文件可写 - 避免把日志写到
/tmp或小分区,尤其是容器环境——/var/log应挂载独立卷
路径过长、轮转缺失、权限不对,三者任一出问题,都会让日志停止写入且无报错提示,只能靠监控磁盘和手动 tail -f 排查。










