1. 程式人生 > >用 awk 和 goaccess 分析nginx accesslog

用 awk 和 goaccess 分析nginx accesslog

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等等詳細資訊。
在這裡插入圖片描述

這種方案還是比較簡單省事的,一步就解決了上面所有的步驟 ,不過我還是選擇上面的方案 ,雖然麻煩,但是有操作感,也能細節到每一步的自定義。