Apache 的 access.log 每天都在增长,里面记录了每一次请求的 IP、时间、路径、状态码和响应大小。如果只是用 grep 或 tail 翻看,很难从几十万行记录中快速判断流量来源、错误率和爬虫行为。GoAccess 是一个专门解决这个问题的终端日志分析器,它直接读取 Apache 日志,无需数据库支持,就能输出交互式 HTML 报告。本文会从安装部署、日志格式匹配、报告生成以及实时监控几个角度,完整说明如何用它分析 Apache 日志。

安装GoAccess与确认Apache日志格式
在 Debian 或 Ubuntu 上,可以直接通过 apt 安装 GoAccess。安装完成后,命令行里会有一个 goaccess 可执行文件,不需要启动额外服务。Red Hat 系列的服务器可以使用 dnf 或 yum 安装,如果官方仓库版本较旧,也可以从源码编译最新版,以启用 GeoIP 和 UTF-8 支持。
# Debian/Ubuntu sudo apt update sudo apt install goaccess # RHEL/CentOS sudo dnf install goaccess
如果希望使用地理位置解析和最新的面板功能,源码编译是更灵活的选择。编译前需要安装 ncurses 开发库,Deiban 系可以执行 sudo apt install libncurses5-dev libncursesw5-dev build-essential。之后下载源码包、配置并编译安装即可。
wget https://tar.goaccess.io/goaccess-1.9.3.tar.gz tar -xzf goaccess-1.9.3.tar.gz cd goaccess-1.9.3 ./configure --enable-utf8 --enable-geoip=legacy make sudo make install
安装完成后,先确认 Apache 日志文件的路径和格式。Debian 和 Ubuntu 通常将日志放在 /var/log/apache2/access.log,CentOS 和 RHEL 则是 /var/log/httpd/access_log。读取日志需要有相应权限,普通用户加入 adm 组或直接使用 sudo 是最常见的做法。Apache 默认提供 common 和 combined 两种格式,combined 多了 Referer 与 User-Agent 字段。GoAccess 内置了 COMMON 和 COMBINED 两个模板,日志如果没有做特殊修改,直接使用 COMBINED 就能正确解析。
解析Apache日志并生成HTML报告
最基本的用法是让 GoAccess 读取 access.log,并以 COMBINED 格式解析,然后输出一个静态 HTML 文件。这个文件可以放在 Web 目录中通过浏览器访问,报告会自动生成多个可交互面板,包括访问量、独立访客、请求文件、静态资源、来源域名、操作系统和浏览器等。相比在终端里查看纯文本统计,HTML 报告更容易快速分享给其他同事。
sudo goaccess /var/log/apache2/access.log --log-format=COMBINED -o /var/www/html/report.html
命令中的 --log-format=COMBINED 表示使用内置的 Apache 组合日志模板,-o 指定输出文件。如果不加 -o,GoAccess 会进入终端交互模式,可以用方向键切换面板、按回车展开细节。终端模式适合在 SSH 会话里快速查看,HTML 模式则适合长期保留或定时生成。
生成的 HTML 报告并不是一个简单的表格,而是一套包含仪表盘、请求状态码占比、访问时间分布等内容的分析页面。主要面板包括:
- 仪表盘:汇总总请求数、独立访客、带宽消耗和响应时间
- 访问量:按小时和日期展示请求趋势
- 请求文件:统计访问最频繁的 URL 和静态资源
- 状态码:展示 2xx、3xx、4xx、5xx 的比例与具体数量
- 来源域名:识别来自搜索引擎和外部站点的流量
如果日志文件很大,可以先通过 --ignore-panel 隐藏一些不需要的面板,减少 HTML 体积。例如只关注状态码和请求文件,可以省略操作系统、浏览器等面板。与 ELK 方案相比,GoAccess 的优势是不需要安装 Elasticsearch 和 Logstash,也不用维护额外进程;缺点是无法对历史日志做大范围的聚合搜索,更适合当天或短期的故障排查。
自定义Apache日志格式如何解析
很多 Apache 站点会根据需求修改 LogFormat,增加响应时间、连接时长或 Cookie 字段。如果这时仍然用 COMBINED 模板,字段位置会对不上,导致报告中 URL 和状态码显示异常。典型表现是状态码列全为 0,或者请求路径里混进了时间、引号等内容。要解决这个问题,需要把 Apache 的日志格式转换成 GoAccess 能够识别的变量。
例如 Apache 中定义了一个扩展格式,除了标准字段外还保留了 Referer 和 User-Agent,对应的配置可能是这样:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" extended
这段配置里,%h 表示客户端 IP,%l 和 %u 通常为空,%t 表示时间,%r 表示请求行,%>s 表示最终状态码,%b 表示响应字节数,后面两个字段分别是 Referer 和 User-Agent。对应到 GoAccess 的命令行,可以写成:
sudo goaccess /var/log/apache2/access.log --log-format='%h %^[%d:%t %^] "%r" %s %b "%R" "%u"' --date-format=%d/%b/%Y --time-format=%T
其中 %^ 用于忽略 Apache 里的空字段,%d 和 %t 分别解析日期和时间,%r 对应请求行,%s 对应状态码,%b 对应字节数,%R 对应 Referer,%u 对应 User-Agent。Apache 默认时间类似 [02/Jan/2024:14:30:12 +0800],因此需要指定 --date-format=%d/%b/%Y 和 --time-format=%T,否则时间字段可能无法正确识别。
如果日志中增加了响应时间字段,例如在请求行后面追加 %D 或 %T,也要在 GoAccess 的格式字符串中增加 %T 或自行定义变量。实际排查时,可以先取一小段日志,用 head 命令截取几十行测试解析,确认报告中的请求路径和状态码不再错位,再解析完整文件。
实时监控与异常请求过滤
当网站正在被爬虫抓取或遭受突发流量时,静态报告无法反映当前状态。GoAccess 提供实时 HTML 模式,可以持续读取日志并通过 WebSocket 推送更新。它的原理是把日志管道输出交给 GoAccess,由其维护一个轻量的 WebSocket 服务,浏览器打开报告页面后会自动刷新数据。这样运维人员可以一边观察流量变化,一边排查问题。
sudo tail -f /var/log/apache2/access.log | goaccess --log-format=COMBINED --real-time-html -o /var/www/html/report_live.html --port=7890
执行命令后,在浏览器中访问 http://服务器IP:7890/report_live.html 就能看到实时更新的报告。需要注意服务器防火墙要放行 7890 端口,或者通过 Nginx 反向代理转发到该端口。如果只在局域网内部排查,可以绑定 127.0.0.1,避免将日志数据暴露到公网。
除了实时模式,GoAccess 还支持多种过滤选项。例如添加 --ignore-crawlers 可以忽略常见搜索引擎爬虫,让统计数据更聚焦真实用户。也可以先用 grep 过滤特定 IP 或路径,再把结果交给 GoAccess 解析:
sudo grep '192.168.1.100' /var/log/apache2/access.log | goaccess --log-format=COMBINED -o filtered.html
这种过滤方式适合追踪某个客户端的完整访问轨迹,但会丢失整体流量上下文。对于几百 MB 以上的日志文件,第一次解析可能较慢,可以加上 --keep-db-files 参数,GoAccess 会在临时目录保留数据库文件,下次解析同一日志时速度会明显提升。实际使用中,建议结合 logrotate 定时切割日志,再配合 GoAccess 定时生成报告,既能保留历史数据,又不会让单次分析的压力过大。

