最近“贪图”便宜,将服务器换到了阿里云国际版香港VPS主机。搬过来后最大的感觉并不是速度的提升——因为原来用的韩国kdatacenter VPS在电信网络访问也是挺快的——而是阿里云VPS主机的性能相对于同样是1GB的其它VPS主机来说真的有点弱了。
稍微用工具一扫阿里云香港VPS的系统负载就蹭蹭往上涨,有时刚在后台写文章就发现打不开了。打开服务器日志一看,发现了不少的异常IP,例如扫描端口的,还有SQL注入的,还有“捡漏”网站备份文件的,还有AB压力测试的……总之,出现不少的非人为的访问行为。
分析日志中的IP行为是一个比较累人的苦力活,尤其是当日志达到几百MB以上时,用文本文件打开就非常地缓慢了。本篇文章就来分享两个优秀的服务器日志分析工具:ngxtop和GoAccess。ngxtop 是通过分析 Nginx 日志文件,使用类似 top 命令的界面实时展示出来的。
ngxtop可以分析以前的日志文件,也可以实时监控服务器日志,你可以像用Top命令一样在端口中快速查出日志中访问最多的IP地址、403/500/404错误、请求的页面排行等等。ngxtop是一个轻量级的工具,而GoAccess则更像是强大的日志统计工具。
GoAccess不仅图文并茂,而且速度快,每秒8W 的日志记录解析速度,websocket每10秒刷新统计数据。GoAccess不仅有命令行界面,也可以生成一个Html网页,让你直观地看出来日志中访客数量、请求的文件、404等错误、用户位置、浏览器、操作系统、来路URL、Http状态码等。
总之,ngxtop和GoAccess是两款分析Apache、Nginx等服务器日志的利器,掌握好了这两个软件,那些对服务器“潜在”的危险IP即可显露“原形”。作为站长,你多学习一个软件的使用,意味着你又可以节省一笔服务器开支,例如:
- 利用Huginn抓取任意网站RSS和微信公众号更新-打造一站式信息阅读平台
- Linux VPS挂载Google Drive和Dropbox-实现VPS主机数据同步备份
- 三大免费工具助你检测VPS服务器真伪-VPS主机性能和速度测试方法
PS:2017年10月21日更新,有兴趣使用阿里云香港VPS的朋友可以先看我的评测:阿里云国际版香港机房速度与性能评测-速度快但磁盘IO和内存是瓶颈。如果你还想监控VPS服务器网络的稳定性,可以使用这个工具:Smokeping安装与配置-免费开源网络性能监控工具可视化主/从部署。
一、ngxtop安装与使用
1.1 ngxtop安装
项目主页:
- https://github.com/lebinh/ngxtop
ngxtop适用于Nginx服务器日志。ngxtop可用如下命令安装:
Fedora:yum install python-pip
CentOS/RHEL需先安装EPEL,安装完后:yum install python-pip
Debian/Ubuntu:apt-get install python-pip
pip install ngxtop
或者也可以直接从源码安装:
wget https://github.com/lebinh/ngxtop/archive/master.zip -O ngxtop-master.zip
unzip ngxtop-master.zip
cd ngxtop-master
python setup.py install
1.2 ngxtop用法
ngxtop的基本用法如下:
gxtop [选项]
ngxtop [选项] (print|top|avg|sum) <变量>
ngxtop info
选项有如下参数:
-l : 指定日志文件的完整路径 (Nginx 或 Apache2)
-f : 日志格式
–no-follow: 处理当前已经写入的日志文件,而不是实时处理新添加到日志文件的日志
-t : 更新频率
-n : 显示行号
-o : 排序规则(默认是访问计数)
-a …, –a …: 添加表达式(一般是聚合表达式如: sum, avg, min, max 等)到输出中。
-v: 输出详细信息
-i : 只处理符合规则的记录
-c <file>或 –config <file> 指定nginx配置文件,自动分析日志格式
-i <filter-expression>或 –filter <filter-expression> 满足表达式的过滤将被处理
-p <filter-expression>或 –pre-filter <filter-expression> in-filter expression to check in pre-parsing phase.
ngxtop的变量有:remote_addr、remote_user、time_local、request、request_path、status、body_bytes_sent、http_referer、http_user_agent
。主要是用来分析出IP地址、请求路径、Http状态、referer、user_agent等等。
1.3 ngxtop示例
用ngxtop info可以查看本机的服务器日志地址还有配置文件所在路径,不过,它只能显示一些默认的日志文件,有一些自定义的日志文件不会显示出来。
找出404错误前十的请求URL。命令代码:
ngxtop -l /data/wwwlogs/wzfou.com_nginx.log --no-follow top request_path --filter 'status == 404'
效果如下图:
找出访问数最多的前十个IP地址。命令代码:
ngxtop -l /data/wwwlogs/wzfou.com_nginx.log --no-follow --group-by remote_addr
效果如下图:
找出流量前十的IP地址。命令代码:
ngxtop -l /data/wwwlogs/wzfou.com_nginx.log --no-follow --order-by 'avg(bytes_sent) * count'
找出400错误代码以上的且显示request、status、http_referer三项。命令代码:
ngxtop -l /data/wwwlogs/wzfou.com_nginx.log --no-follow -i 'status >= 400' print request status http_referer
找出bytes_sent平均值且状态码为200且request_path以wzfou开头的前10。命令代码:
ngxtop -l /data/wwwlogs/wzfou.com_nginx.log --no-follow avg bytes_sent --filter 'status == 200 and request_path.startswith("wzfou")'
通过上面几个命令,基本上很快就能锁定一些异常请求的IP地址了。默认的ngxtop会显示前10个记录,你可以加上参数 –n xxx,这样自己控制显示的数量。命令如下:
ngxtop -l /data/wwwlogs/wzfou.com_nginx.log --no-follow --group-by remote_addr -n 20
ngxtop实现监控服务器日志。要想实时显示Nginx日志监控的情况,只需要去年–no-follow 参数即可,命令如下:
ngxtop -l /data/wwwlogs/wzfou.com_nginx.log --group-by remote_addr
效果如下图:
二、GoAccess安装与使用
2.1 GoAccess安装
GoAccess官网:
- https://goaccess.io/
GoAccess支持Apache、Nginx、 Amazon S3、 Elastic Load Balancing、CloudFront等服务器日志的分析。安装命令如下:
apt-get install libncursesw5-dev libgeoip-dev
wget http://tar.goaccess.io/goaccess-1.2.tar.gz
tar -xzvf goaccess-1.2.tar.gz
cd goaccess-1.2/
./configure --enable-utf8 --enable-geoip=legacy
make
make install
根据你自己的需要,你可以在安装GoAccess 调整配置选项。如下:
--enable-debug
使用调试标志编译且关闭编译器优化。--enable-utf8
宽字符支持。依赖 Ncursesw 模块。--enable-geoip=<legacy|mmdb>
地理位置支持。依赖 MaxMind GeoIP 模块。 legacy 将使用原始 GeoIP 数据库。 mmdb 将使用增强版 GeoIP2 数据库。--enable-tcb=<memhash|btree> Tokyo Cabinet
存储支持。 memhash 将使用 Tokyo Cabinet 的内存哈希数据库。btree 将使用 Tokyo Cabinet 的磁盘 B+Tree 数据库。
–disable-zlib 禁止在 B+Tree 数据库上使用 zlib 压缩。--disable-bzip
禁止在 B+Tree 数据库上使用 bzip2 压缩。--with-getline 使
用动态扩展行缓冲区用来解析完整的行请求,否则将使用固定大小(4096)的缓冲区。--with-openssl
使 GoAccess 与其 WebSocket 服务器之间的通信能够支持 OpenSSL。
2.2 GoAccess用法
GoAccess语法如下:
goaccess [filename] [ options ... ] [-c][-M][-H][-q][-d][...]
常用的参数说明如下:
-f –log-file=<logfile>
指定输入日志文件的路径。如果在配置文件中指定了输入文件,则其优先级要高于在命令行中通过
-f
参数指定。-l –log-debug=<filename>
发送所有调试信息到指定文件。需要指定配置选项
--enable-debug
-p –config-file=<configfile>
指定使用自定义配置文件。如果设置了此参数,其优先级将高于全局配置文件(如果有)。
–invalid-requests=<filename>
记录无效请求到指定文件。
–no-global-config
禁止加载全局配置文件。可能的目录应该是
/usr/etc/
,/etc/
或者/usr/local/etc/
, 除非在运行 ./configure 时指定了--sysconfdir=/dir
。-a –agent-list
开启 UserAgent 列表。开启后会降低解析速度。
-d –with-output-resolver
输出
HTML
或者JSON
报告时开启 IP 解析。-e –exclude-ip <IP|IP-range>
排除一个 IPv4 或者 IPv6 地址。 使用连接符表示 IP 段(开始-结束)。
-H –http-protocol=<yes|no>
HTTP 请求协议开关。将创建一个请求字段包含请求协议+真实请求。
-M –http-method=<yes|no>
HTTP 请求方法开关。将创建一个请求字段包含请求方法+真实请求。
-o –output=<json|csv>
将给定文件重定向到标准输出,通过后缀名决定输出格式:
-q –no-query-string
忽略请求的查询字符串。即: www.google.com/page.htm?query => www.google.com/page.htm
注意: 去掉查询字符串将极大降低内存消耗,特别对带时间戳的请求。-r –no-term-resolver
在终端输出时禁止 IP 解析。
–444-as-404
将非标准状态 444 作为 404 处理。
–4xx-to-unique-count
将 4xx 客户端错误数加到独立访客数中。
–all-static-files
统计包含查询字符串的静态文件。
–date-spec=<date|hr>
设置日期的显示格式,一种是标准日期格式(默认),一种是日期后附加小时的格式。
仅在访客面板有效。对于在小时级别分析访客数据很有帮助。显示格式示例:18/Dec/2010:19
–double-decode
解码双重编码的值。包括 UserAgent,Request 以及 Referer。
–enable-panel=<PANEL>
开启指定面板。面板列表:
–hour-spec=<hour|min>
设定时间的显示格式,一种是标准时间格式(默认),一种是时间后附加分钟数(每十分钟)的格式。
用于时间分布面板。对于在特定时间段分析流量峰值很有用处。–ignore-crawlers
忽略爬虫。
–ignore-panel=<PANEL>
忽略指定面板。面板列表:
–ignore-referer=<referer>
忽略被统计的来路。支持通配符。例如:
*.domain.com
ww?.domain.*
–ignore-status=<STATUS>
忽略解析或者显示一个或者多个状态码。如果有多个状态码,使用此参数每次指定一个。
–num-tests=<number>
设定测试行数,即使用给定的 日志/日期/时间 格式测试访问日志。默认值为 10 行。如果设置为 0 ,解析器不会做任何测试而是直接解析整个文件。如果在达到
number
之前,有一行匹配上了给定的 日志/日期/时间 格式,则解析器会认为日志文件是有效的,否则 GoAccess 会返回EXIT_FAILURE
并显示相关的错误信息。–process-and-exit
解析日志,且退出时不输出数据。主要用于仅希望往磁盘数据库中添加数据而无需输出报告时使用。
–real-os
显示真实的操作系统名称。例如: Windows XP, Snow Leopard.
–sort-panel=<PANEL,FIELD,ORDER>
S在初始化载入是对面板进行排序。排序选项使用逗号分隔。选项使用这样的格式:PANEL,METRIC,ORDER
–static-file <extension>
添加静态文件后缀名。例如:
.mp3
。 后缀名区分大小写。-g –std-geoip
标准 GeoIP 数据库,低内存占用。
–geoip-database <geocityfile>
设定 GeoIP 数据库路径。例如:GeoLiteCity.dat。需要从 maxmind.com 上下载到本地。IPv4 和 IPv6 均可用支持。注意:
--geoip-city-data
是--geoip-database
的别名。
注意: 如果使用 GeoIP2,您需要从 MaxMind 下载 城市/国家 数据库,并通过--geoip-database
设定。
GoAccess日志格式。GoAccess还有一个参数是用来设置服务器日志格式的:–log-format <logformat>。参数 log-format 后跟随一个空格符或者制表分隔符(t
),用于指定日志字符串格式。
如果你使用的是下表中的预定义日志格式名称,可以直接当作GoAccess 日志/日期/时间 格式的变量。
COMBINED | 联合日志格式 VCOMBINED | 支持虚拟主机的联合日志格式 COMMON | 通用日志格式 VCOMMON | 支持虚拟主机的通用日志格式 W3C | W3C 扩展日志格式 SQUID | Native Squid 日志格式 CLOUDFRONT | 亚马逊 CloudFront Web 分布式系统 CLOUDSTORAGE | 谷歌云存储 AWSELB | 亚马逊弹性负载均衡 AWSS3 | 亚马逊简单存储服务 (S3)
2.3 如何设置日志格式
首先看看你的log_format是什么,log_format指令如下:
语法: log_format name string …;
默认值: log_format combined “…”;
配置段: http
name表示格式名称,string表示等义的格式。log_format有一个默认的无需设置的combined日志格式,相当于apache的combined日志格式,如下所示:
log_format combined '$remote_addr - $remote_user [$time_local] '
' "$request" $status $body_bytes_sent '
' "$http_referer" "$http_user_agent" ';
当然,你也可以根据自己的需要来添加服务器日志需要获取的信息。以下是日志格式允许包含的变量:
remote_addr, $http_x_forwarded_for 记录客户端IP地址
remote_user 记录客户端用户名称
request 记录请求的URL和HTTP协议
status 记录请求状态
body_bytes_sent 发送给客户端的字节数,不包括响应头的大小; 该变量与Apache模块mod_log_config里的“%B”参数兼容。
bytes_sent 发送给客户端的总字节数。
connection 连接的序列号。
connection_requests 当前通过一个连接获得的请求数量。
msec 日志写入时间。单位为秒,精度是毫秒。
pipe 如果请求是通过HTTP流水线(pipelined)发送,pipe值为“p”,否则为“.”。
http_referer 记录从哪个页面链接访问过来的
http_user_agent 记录客户端浏览器相关信息
request_length 请求的长度(包括请求行,请求头和请求正文)。
request_time 请求处理时间,单位为秒,精度毫秒; 从读入客户端的第一个字节开始,直到把最后一个字符发送给客户端后进行日志写入为止。
time_iso8601 ISO8601标准格式下的本地时间。
time_local 通用日志格式下的本地时间。
以下是log_format设置实例:
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'"$status" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'"$gzip_ratio" $request_time $bytes_sent $request_length';
log_format srcache_log '$remote_addr - $remote_user [$time_local] "$request" '
'"$status" $body_bytes_sent $request_time $bytes_sent $request_length '
'[$upstream_response_time] [$srcache_fetch_status] [$srcache_store_status] [$srcache_expire]';
open_log_file_cache max=1000 inactive=60s;
server {
server_name ~^(www.)?(.+)$;
access_log logs/$2-access.log main;
error_log logs/$2-error.log;
location /srcache {
access_log logs/access-srcache.log srcache_log;
}
}
}
这是GoAccess日志格式与服务器log-format对应关系:
%t 匹配time-format格式的时间字段
%d 匹配date-format格式的日期字段
%h host(客户端ip地址,包括ipv4和ipv6)
%r 来自客户端的请求行
%m 请求的方法
%U URL路径
%H 请求协议
%s 服务器响应的状态码
%b 服务器返回的内容大小
%R HTTP请求头的referer字段
%u 用户代理的HTTP请求报头
%D 请求所花费的时间,单位微秒
%T 请求所花费的时间,单位秒
%^ 忽略这一字段
GoAccess日志修改示例:
log_format access '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $http_x_forwarded_for $request_time $upstream_response_time';
GoAccess默认的配置文件goaccess.conf
放置于/usr/local/etc
路径中,默认的格式是:log-format %h %^[%d:%t %^] "%r" %s %b "%R" "%u"。
观察上面的服务器日志格式,发现多了响应时间$request_time
和upstream的响应时间$upstream_response_time。
我们可以修改如下:
原来:log-format %h %^[%d:%t %^] "%r" %s %b "%R" "%u"
修改:log-format %h %^[%d:%t %^] "%r" %s %b "%R" "%u" %^ %^ %T
最后三个元素%^ %^ %T
,%^
表示忽略,%T
表示“以秒为单位的响应时间,精确到毫秒”。通过修改GoAccess的格式就与我们的服务器日志格式对应上了。
2.4 GoAccess示例
如果你的服务器用的是通用日志格式,联合日志格式,包含虚拟主机,W3C 格式以及亚马逊 CloudFront(分布式下载)等,就不需要修改日志格式,直接使用即可。LNMP和Oneinstack都是用的COMBINED格式。
GoAccess在终端在分析日志命令:
goaccess -d -f /data/wwwlogs/wzfou.com_nginx.log --log-format=COMBINED
以上命令中,-f 指定要分析的日志/path/to/log;–log-format 日志的格式,LNMP默认格式为:COMBINED。运行后效果如下图:
操作热键如下:
F1
或h
主帮助页面。
F5
重绘主窗口。
q
退出程序,当前窗口或者崩溃了的模块。
o
或ENTER
扩展选中的模块或打开窗口。
0-9
和Shift + 0
激活选中的模块。
j
在已扩展模块中向下滚动。
k
在已扩展模块中向上滚动。
c
设置或者改变配色方案。
^ f
在当前模块中向前滚动一屏。
^ b
在当前模块中向后滚动一屏。
TAB
切换模块(向前)。
SHIFT + TAB
切换模块(向后)。
s
给活跃模块的选项排序。
/
在所有模块中搜索(支持正则)。
n
找到下次发生事件的位置。
g
移动到第一个选项或者屏幕顶部。
G
移动到第最后一个选项或者屏幕底部。
如果你想要查看访问数前十的IP地址,按下数字键5,就可以打开该模块详情了。如下图:
其它的几个数字对应模块如下:
按 1 定位到“按天访问量”
按 2 定位到“最多次被请求的 URL”
按 3 定位到“最多次被请求的静态文件”
按 4 定位到“最多次被请求的 404”
按 5 定位到“最多次请求的用户 IP”
按 6 定位到“用户的操作系统”
按 7 定位到“用户的浏览器”
按 8 定位到“按小时的统计”
GoAccess输出。 命令如下:
生成一份 HTML 报告:
# goaccess access.log -a -o report.html
生成一份 JSON 报告:
# goaccess access.log -a -d -o report.json
生成一份 CSV 文件:
# goaccess access.log --no-csv-summary -o report.csv
GGoAccess 非常灵活,支持实时解析和过滤。例如:需要通过监控实时日志来快速诊断问题:
# tail -f access.log | goaccess -
更厉害的是,还可以使用 tail -f 和一个模式匹配工具一起工作,比如: grep
, awk
, sed
等等
# tail -f access.log | grep -i --line-buffered 'firefox' | goaccess --log-format=COMBINED -
又或者可以在管道打开的状态下从头开始解析文件,并同时应用一个过滤器:
# tail -f -n +0 access.log | grep --line-buffered 'Firefox' | goaccess -o out.html --real-time-html -
例如:
将GoAccess输出Html,然后用浏览器访问,可用以下命令:
goaccess -d -f /data/wwwlogs/wzfou.com_nginx.log --log-format=COMBINED -a > /data/wwwroot/howsvps.com/wzfou.html
用浏览器访问效果如下图(点击放大):
GoAccess输出的图表非常漂亮,你还可在图表中查看详细的选项。详情还可以看看官网的Demo:https://rt.goaccess.io/
将GoAccess输出Html并实时刷新,命令如下:
goaccess -d -f /data/wwwlogs/howsvps.com_nginx.log --log-format=COMBINED -a > /data/wwwroot/howsvps.com/wzfou.html --real-time-html --port=9870 --daemonize
以上是守护进程启动 GoAccess 后,使用 Websocket 建立长连接,它默认监听 7890 端口,可以通过--port
参数指定端口号。
指定端口号后,记得在你的VPS防火墙中打开:
iptables -A INPUT -p tcp -m tcp --dport 9870 -j ACCEPT
三、总结
ngxtop适合简单的查找需要,GoAccess偏重于整体分析,甚至可以当成统计使用。如果你的网站使用的SSL,那么在GoAccess输出实时监控的HTML页面时,记得在在配置文件goaccess.conf
中配置ssl-cert
和ssl-key
项。
当然,我们也可以使用crontab定时让GoAccess生成统计html页面,这样也相当于实时在线监控服务器日志了。代码如下(每5分钟生成一次HtmL页面):
*/5 * * * * goaccess -d -f /data/wwwlogs/wzfou.com_nginx.log --log-format=COMBINED -a > /data/wwwroot/wzfou.com/wzfou.html
对于不知道如何设置GoAccess日志格式的朋友,你可以直接使用在线转换工具:https://github.com/stockrt/nginx2goaccess。命令:
用法: ./nginx2goaccess.sh '<log_format>' ./nginx2goaccess.sh '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"'
输出的结果你就可以直接用在GoAccess日志格式设置中了:
- Generated goaccess config: time-format %T date-format %d/%b/%Y log_format %h - %^ [%d:%t %^] "%r" %s %b "%R" "%u"