awstats作為一款日志分析軟體,功能不錯,但是界面過于簡單,也沒有圖表功能,這裡我采取了一種變通的方法,将awstats的分析結果(pv、hits(檔案數)、bandwidth、visits(獨立ip))添加到zabbix,并通過zabbix生成趨勢圖表。
在前兩篇文章中,我們隊awstats的使用及其工作方式進行了簡明扼要的介紹:awstats對每個站點進行分析之後,會生成一個“awstats012016.txt”格式的“資料庫”檔案;awstats的展示頁面便是從該檔案中取資料生成的。
<a href="http://kaifly.blog.51cto.com/3209616/1719248" target="_blank"> 1. 多server多站點情況下awstats日志分析</a>
<a href="http://kaifly.blog.51cto.com/3209616/1770137" target="_blank"> 2. awstats CGI模式下動态生成頁面緩慢的改進</a>
這篇文章的思路就是從這個文本格式的‘資料庫檔案’中取得我們想要的資料,然後通過自定義的腳本将其添加到zabbix中,最終滿足我們生成pv趨勢圖表的需求。
而完成此任務的關鍵就是分析似‘awstats052016.txt’的資料檔案的内容格式(ps:以筆者“多年”shell經驗來看,”分析源檔案格式“和“生成目标檔案格式”這倆“格式”在日常的shell程式設計中占用了很大一部分時間。扯遠了O(∩_∩)O~)
首先是自定義腳本作為zabbix的key,從對應的‘資料檔案’中取得pv、hits、bandwidth、visits的值。用shell實作如下
cat web_pv.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<code>#!/bin/sh</code>
<code>#從例如api/awstats052016.txt這樣的awstats資料庫檔案裡取得昨天的pv等統計(因為awstats本身就是統計到昨天的日志)</code>
<code>#by ljk 20160506</code>
<code>#blog http://kaifly.blog.51cto.com/</code>
<code>#shell腳本的$1 $2分别代表站點名稱(格式如www或bbs)和統計項(pv 檔案數 位元組 獨立ip)</code>
<code>basedir=</code><code>'/usr/local/awstats-7.4/result'</code>
<code>date_f1=$(</code><code>date</code> <code>+%m%Y -d </code><code>'1 day ago'</code><code>)</code>
<code>date_f2=$(</code><code>date</code> <code>+%Y%m%d -d </code><code>'1 day ago'</code><code>)</code>
<code>cd</code> <code>$basedir/$1</code>
<code>#下面關于awk的用法中有一個小技巧,比對到指定的項之後,停止繼續搜尋餘下的内容。這對于體積較大的檔案可以節約不少時間</code>
<code>content=`</code><code>awk</code> <code>'$1 == "'</code><code>$date_f2</code><code>'" {{print} {exit}}'</code> <code>awstats$date_f1\.txt`</code>
<code>case</code> <code>$2 </code><code>in</code>
<code> </code><code>"pages"</code><code>)</code>
<code> </code><code>echo</code> <code>$content|</code><code>awk</code> <code>'{print $2}'</code><code>;; </code><code>#pv</code>
<code> </code><code>"hits"</code><code>)</code>
<code> </code><code>echo</code> <code>$content|</code><code>awk</code> <code>'{print $3}'</code><code>;; </code><code>#hits/檔案數</code>
<code> </code><code>"bandwidth"</code><code>)</code>
<code> </code><code>echo</code> <code>$content|</code><code>awk</code> <code>'{print $4}'</code><code>;; </code><code>#bandwidth/位元組</code>
<code> </code><code>"visits"</code><code>)</code>
<code> </code><code>echo</code> <code>$content|</code><code>awk</code> <code>'{print $5}'</code><code>;; </code><code>#visits/獨立ip</code>
<code> </code><code>*)</code>
<code> </code><code>echo</code> <code>"unknow value"</code><code>;;</code>
<code>esac</code>
然後在awstats所在的server的zabbix的‘userparameter.conf’檔案中添使用者自定義key,并重新開機zabbix_agentd
<code>UserParameter=web_pv[*],</code><code>/bin/sh</code> <code>/usr/local/zabbix/etc/zabbix_agentd</code><code>.conf.d</code><code>/web_pv</code><code>.sh $1 $2</code>
接着在zabbix_server端通過zabbix_get指令嘗試擷取這些值,key格式為“web_pv[站點名,監控項]”,例如
能取到值,說明自定義key是ok的。
接下來就是在zabbix裡添加各站點的item了,這裡通過Python實作(zbx接口通過json傳遞資料,處理json python比shell友善太多了)
首先在zabbix裡建立一個template,名為Template site PV,這一步手動建立即可
然後開始通過Python自動化添加items
cat shells/add_web-pv_item_to_zabbix.py
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<code>#!/bin/env python3</code>
<code>"""</code>
<code>将各站點的4種(pages,hits,bandwidth,visits)item添加/更新到zabbix的 'Template Site-PV'</code>
<code>by ljk 20160507</code>
<code>import</code> <code>os,requests</code>
<code>basedir</code><code>=</code><code>'/usr/local/services/awstats-7.4/result/'</code>
<code>items</code><code>=</code><code>[</code><code>'pages'</code><code>,</code><code>'hits'</code><code>,</code><code>'bandwidth'</code><code>,</code><code>'visits'</code><code>]</code>
<code>url</code><code>=</code><code>'http://192.168.1.199/api_jsonrpc.php'</code>
<code>zbx_api_headers</code><code>=</code><code>{</code><code>'Content-Type'</code><code>:</code><code>'application/json-rpc'</code><code>} </code><code>#定義通過zabbix api操作時必帶的header</code>
<code>#取得用于zabbix api認證的token,通過使用者名密碼請求api生成</code>
<code>#生成方式請參考api文檔,有個這個token,可以省去賬号密碼認證</code>
<code>api_auth</code><code>=</code><code>"738024dfda33cc6020fb1f5e3617"</code>
<code>#這裡我在前期實驗的時候,手動添加了幾個item了,是以這裡先取出template裡已經存在的item,以便後期建立時過濾掉這些item</code>
<code>exist_items_filter</code><code>=</code><code>{ </code><code>#通過zabbix api查詢已經存在的web_pv[*,*]的item,這裡是json格式的過濾條件</code>
<code> </code><code>"jsonrpc"</code><code>: </code><code>"2.0"</code><code>,</code>
<code> </code><code>"method"</code><code>: </code><code>"item.get"</code><code>,</code>
<code> </code><code>"params"</code><code>: {</code>
<code> </code><code>"output"</code><code>:[</code>
<code> </code><code>"name"</code><code>,</code>
<code> </code><code>],</code>
<code> </code><code>"search"</code><code>: {</code>
<code> </code><code>"key_"</code><code>:</code><code>"web_pv"</code>
<code> </code><code>}</code>
<code> </code><code>},</code>
<code> </code><code>"auth"</code><code>:api_auth,</code>
<code> </code><code>"id"</code><code>: </code><code>0</code>
<code>}</code>
<code>exist_items</code><code>=</code><code>requests.post(url,headers</code><code>=</code><code>zbx_api_headers,json</code><code>=</code><code>exist_items_filter)</code>
<code>os.chdir(basedir)</code>
<code>sites</code><code>=</code><code>os.listdir(path</code><code>=</code><code>'.'</code><code>)</code>
<code>def</code> <code>create_item():</code>
<code> </code><code>for</code> <code>site </code><code>in</code> <code>sites:</code>
<code> </code><code>for</code> <code>item </code><code>in</code> <code>items:</code>
<code> </code><code>if</code> <code>site</code><code>+</code><code>'-'</code><code>+</code><code>item </code><code>not</code> <code>in</code> <code>exist_items.text:</code>
<code> </code><code>#先給不同情況下的units和multiplier指派</code>
<code> </code><code>if</code> <code>item</code><code>=</code><code>=</code><code>'pages'</code> <code>or</code> <code>item</code><code>=</code><code>=</code><code>'hits'</code><code>:</code>
<code> </code><code>units</code><code>=</code><code>'萬'</code>
<code> </code><code>multiplier</code><code>=</code><code>0.0001</code>
<code> </code><code>elif</code> <code>item</code><code>=</code><code>=</code><code>'bandwidth'</code><code>:</code>
<code> </code><code>units</code><code>=</code><code>'B'</code>
<code> </code><code>multiplier</code><code>=</code><code>1</code>
<code> </code><code>else</code><code>:</code>
<code> </code><code>units</code><code>=</code><code>''</code>
<code> </code><code>#定義建立item的json資料格式</code>
<code> </code><code>num</code><code>=</code><code>10</code>
<code> </code><code>create_item_post</code><code>=</code><code>{</code>
<code> </code><code>"jsonrpc"</code><code>: </code><code>"2.0"</code><code>,</code>
<code> </code><code>"method"</code><code>: </code><code>"item.create"</code><code>,</code>
<code> </code><code>"params"</code><code>: {</code>
<code> </code><code>"name"</code><code>: site</code><code>+</code><code>','</code><code>+</code><code>item,</code>
<code> </code><code>"key_"</code><code>: </code><code>"www_pv["</code><code>+</code><code>site</code><code>+</code><code>','</code><code>+</code><code>item</code><code>+</code><code>"]"</code><code>,</code>
<code> </code><code>"hostid"</code><code>: </code><code>"10134"</code><code>,</code>
<code> </code><code>"type"</code><code>: </code><code>0</code><code>,</code>
<code> </code><code>"value_type"</code><code>: </code><code>3</code><code>,</code>
<code> </code><code>"history"</code><code>: </code><code>7</code><code>,</code>
<code> </code><code>"delay"</code><code>: </code><code>28800</code><code>,</code>
<code> </code><code>"units"</code><code>: units,</code>
<code> </code><code>"applications"</code><code>: [</code><code>774</code><code>],</code>
<code> </code><code>"interfaceid"</code><code>: </code><code>"0"</code><code>,</code>
<code> </code><code>"formula"</code><code>: multiplier</code>
<code> </code><code>},</code>
<code> </code><code>"auth"</code><code>: api_auth,</code>
<code> </code><code>"id"</code><code>: num</code>
<code> </code><code>}</code>
<code> </code><code>try</code><code>:</code>
<code> </code><code>create_item_result</code><code>=</code><code>requests.post(url,headers</code><code>=</code><code>zbx_api_headers,json</code><code>=</code><code>create_item_post) </code>
<code> </code><code>#列印處理每個條目的結果</code>
<code> </code><code>print</code><code>(</code><code>'{}-{}: return_code {} details {}'</code><code>.</code><code>format</code><code>(site,item,create_item_result.status_code,create_item_result.json))</code>
<code> </code><code>num</code><code>+</code><code>=</code><code>1</code>
<code> </code><code>except</code><code>:</code>
<code> </code><code>print</code><code>(</code><code>'{}-{}: error'</code><code>.</code><code>format</code><code>(site,item))</code>
<code> </code><code>import</code> <code>sys</code>
<code> </code><code>sys.exit(</code><code>255</code><code>)</code>
<code>#create_item()</code>
<code>#update函數,其實是我在執行create_item()的時候将key的名字寫錯了,無奈在寫一個update_item()吧</code>
<code>def</code> <code>update_item():</code>
<code> </code><code>num</code><code>=</code><code>100</code> <code>#對應zbx api中的id字段,随意指定,確定每次調用api時該值不同即可(這裡用自增的方式)</code>
<code> </code><code>#定義更新item的json資料格式</code>
<code> </code><code>update</code><code>=</code><code>{</code>
<code> </code><code>"jsonrpc"</code><code>: </code><code>"2.0"</code><code>,</code>
<code> </code><code>"method"</code><code>: </code><code>"item.update"</code><code>,</code>
<code> </code><code>"params"</code><code>: {</code>
<code> </code><code>"itemid"</code><code>: "",</code>
<code> </code><code>"key_"</code><code>: ""</code>
<code> </code><code>},</code>
<code> </code><code>"auth"</code><code>: api_auth,</code>
<code> </code><code>"id"</code><code>: num</code>
<code> </code><code>}</code>
<code> </code><code>#取得site pv模闆下所有錯誤的item(key以www_py開頭的),hostid的值實際為template site PV模闆的templateid</code>
<code> </code><code>wrong_items_filter</code><code>=</code><code>{</code>
<code> </code><code>"jsonrpc"</code><code>: </code><code>"2.0"</code><code>,</code>
<code> </code><code>"method"</code><code>: </code><code>"item.get"</code><code>,</code>
<code> </code><code>"params"</code><code>: {</code>
<code> </code><code>"output"</code><code>:[</code><code>"key_"</code><code>,</code><code>"hostid"</code><code>],</code>
<code> </code><code>"search"</code><code>: {</code><code>"hostid"</code><code>:</code><code>"10134"</code><code>,</code><code>"key_"</code><code>:</code><code>"www_pv"</code><code>}</code>
<code> </code><code>},</code>
<code> </code><code>"auth"</code><code>: api_auth,</code>
<code> </code><code>"id"</code><code>: </code><code>0</code>
<code> </code><code>wrong_items</code><code>=</code><code>requests.post(url,headers</code><code>=</code><code>zbx_api_headers,json</code><code>=</code><code>wrong_items_filter).json()[</code><code>'result'</code><code>] </code><code>#wrong_items為list</code>
<code> </code><code>for</code> <code>wrong_item </code><code>in</code> <code>wrong_items:</code>
<code> </code><code>if</code> <code>wrong_item[</code><code>'hostid'</code><code>] !</code><code>=</code> <code>'10119'</code><code>: </code><code>#img2從template site pv繼承而來 是以這裡每個item對應兩條記錄對應template site pv的hostid:10134和img2的hostid:10119,是以不需要修改img2的</code>
<code> </code><code>update[</code><code>'params'</code><code>][</code><code>'itemid'</code><code>]</code><code>=</code><code>wrong_item[</code><code>'itemid'</code><code>]</code>
<code> </code><code>update[</code><code>'params'</code><code>][</code><code>'key_'</code><code>]</code><code>=</code><code>wrong_item[</code><code>'key_'</code><code>].replace(</code><code>'www'</code><code>,</code><code>'web'</code><code>,</code><code>1</code><code>) </code>
<code> </code><code>try</code><code>:</code>
<code> </code><code>update_item_result</code><code>=</code><code>requests.post(url,headers</code><code>=</code><code>zbx_api_headers,json</code><code>=</code><code>update)</code>
<code> </code><code>print</code><code>(</code><code>'{} ---- details {}'</code><code>.</code><code>format</code><code>(wrong_item[</code><code>'key_'</code><code>],update_item_result.json()))</code>
<code> </code><code>num</code><code>+</code><code>=</code><code>1</code>
<code> </code><code>except</code><code>:</code>
<code> </code><code>print</code><code>(</code><code>'{}-{}: error'</code><code>.</code><code>format</code><code>(site,item))</code>
<code> </code><code>import</code> <code>sys</code>
<code> </code><code>sys.exit(</code><code>255</code><code>)</code>
<code>#update_item()</code>
後續的批量生成image和生成screen都可以通過zbx 的API來完成,這裡就不再列舉了
ok,最後看兩張zabbix生成的靓圖吧
<a href="http://s5.51cto.com/wyfs02/M02/80/00/wKiom1cz7y3gx8H_AAFbYDcLV3Q395.png" target="_blank"></a>
<a href="http://s1.51cto.com/wyfs02/M01/80/00/wKiom1cz77qSrYKWAAGSoXMhnv4994.png" target="_blank"></a>
本文轉自kai404 51CTO部落格,原文連結:http://blog.51cto.com/kaifly/1772377,如需轉載請自行聯系原作者