用 awk 和 goaccess 分析nginx accesslog
阿新 • • 發佈:2018-11-20
awk 方式
本文主要用這種方式實現 統計 access.log
超過 1s 的記錄。
思路:先用 awk
將每天切割的 nginx
日誌生成自定義的分析結果檔案 ,由 python 指令碼處理,匯入mysql
:記錄日期
,慢Url 路徑
,慢Url 最短時間
,最差時間
,訪問次數
,是否修復
,修復日期
等,最後由前端進行展示。
按天切割 Nginx 日誌
這裡為了每天夜裡只分析當天生成的nginx日誌,我們可以把nginx按天切割備份。日常環境中,我們也可以使用這種方法,按天、按月、按年lai 備份和切割日誌,方便後期進行資料過濾或刪除。
#/bin/bash
nginxLog= "/usr/local/nginx/logs/access.log"
logBakFile="/usr/local/nginx/logs/"$(date "+%F")/"access.log"
if [ ! -d ${logBakFile%/*} ]
then
mkdir -p ${logBakFile%/*}
fi
mv $nginxLog $logBakFile 2>&1 >/dev/null
kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`
#切割nginx日誌 59 23 * * * bash /root/auto-sh/nginxErrLog_logrotate.sh 59 22 * * * bash /root/auto-sh/nginxAccLog_logrotate.sh
這樣,我們就得到了,這樣的Nginx切割的日誌
[[email protected] 2018-10-08]# ls
access.log error.log
這裡我們對 access.log
進行處理
附上 nginx.conf
日誌格式部分的配置:
log_format main "$remote_addr $http_x_readtime [$time_local] \ "$request_method http://$host$request_uri\" $status $body_bytes_sent \"$http_referer\" \"$upstream_addr\" \ "$http_user_agent\" \"$upstream_response_time\" \"$request_time\" ";
Awk
指令碼
#分析nginx日誌 需要去除 每天備份的log“” 儲存到1.txt
cat access.log| awk '{print $(NF)}' | awk -F "\"" '{print $2}'>1.txt
#將 1.txt的結果拼接到 access.log 存放到log.txt
paste -d " " access.log 1.txt > log.txt
# 從 log.txt 選取想要分析的引數存放到最終的檔案中,限制選取 $request_time >1 的
cat log.txt |awk '($NF>1 ){print $3 " " $5 " " $6 " " $11 " " $NF}'>/public/nginxStatic.txt
訪問 nginxStatic.txt
的結果:可以看到有我們選取的 http_x_readtime
,$request_method
,$request_uri
,$http_user_agent
, $request_time
。
最後用 python
,將資料處理分析之後儲存到mysql。
附上思路程式碼:
import MySQLdb as mdb
from tqdm import tqdm
# 統計 access.log 超過 1S 的記錄
# AWK 將每天的nginx日誌 產生log ,由本指令碼 匯入sql,記錄
# 日期,慢Url 路徑,慢Url 最短時間,最差時間,訪問次數 ,是否修復 ,修復日期
# 前端進行展示
# 定義日誌檔案路徑
log_file_path = "/statics/nginxStatic.txt"
# 按行讀取日誌,過濾分析 存入mysql
f = open(log_file_path)
lines = f.readlines()
for line in tqdm(lines):
# 用 " " 切分單行資料
tmp_list = line.split(" ")
api_time = tmp_list[0].replace("[","")
api_method = tmp_list[1].replace("\"","")
api_url = tmp_list[2].replace("\"","")
api_ua = tmp_list[3].replace("\"","")
api_request_time = tmp_list[4].replace("\n","")
# print(api_request_time)
# sys.exit(0)
is_fix = get_nginx_log(api_url)
if is_fix:
# 更新log的頻率 ,更新sl_time
id = is_fix[0][0]
s_time = is_fix[0][1]
l_time = is_fix[0][2]
if api_request_time > s_time and api_request_time < l_time:
update_nginx_log(id,1,api_request_time)
elif api_request_time < s_time:
update_nginx_log(id,2,api_request_time)
elif api_request_time > l_time:
update_nginx_log(id, 3, api_request_time)
else:
insert_nginx_log(api_time, api_url, api_ua, api_request_time,api_method)
資料表的表結構:
CREATE TABLE `nginxlog` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'log自增ID',
`url` varchar(256) NOT NULL DEFAULT '',
`method` varchar(20) DEFAULT NULL COMMENT '呼叫方法',
`ua` varchar(128) DEFAULT NULL COMMENT 'user_agent',
`short_time` decimal(5,2) DEFAULT '0.00' COMMENT '最短時間',
`long_time` decimal(5,2) DEFAULT '0.00' COMMENT '最長時間',
`is_fix` tinyint(1) unsigned DEFAULT '0' COMMENT '0未修復',
`number` int(11) DEFAULT '1' COMMENT '訪問次數',
`create_time` varchar(128) DEFAULT '',
`fix_time` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=utf8mb4;
跑完之後的資料,可以很方便的給前端進行資料呼叫和展現了
goaccess
#安裝(或原始碼安裝)
apt-get install goaccess
$ goaccess -h
# 常用引數
-a --agent-list 啟用由主機使用者代理的列表。為了更快的解析,不啟用該項
-d --with-output-resolver 在HTML/JSON輸出中開啟IP解析,會使用GeoIP來進行IP解析
-f --log-file 需要分析的日誌檔案路徑
-p --config-file 配置檔案路徑
-o --output 輸出格式,支援html、json、csv
-m --with-mouse 控制面板支援滑鼠點選
-q --no-query-string 忽略請求的引數部分
--real-time-html 實時生成HTML報告
--daemonize 守護程序模式,--real-time-html時使用
# 生成視覺化html報告
goaccess -f /usr/local/nginx/logs/access.log -a > /public/report.html
生成的報告頁面預覽如下:能看到各種狀態碼的訪問次數,日PV,UV等等詳細資訊。
這種方案還是比較簡單省事的,一步就解決了上面所有的步驟 ,不過我還是選擇上面的方案 ,雖然麻煩,但是有操作感,也能細節到每一步的自定義。