最近「貪圖」便宜,將伺服器換到了阿里雲國際版香港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/樂賓虹/那小top
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://go access.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"