RRDtool簡體中文教程 v1.01 – 3
RRDtool簡體中文教程_5:如何獲取RRD文件的信息
獲取 RRD 文件的信息
**********************************************************************************************************************
注 :該教程參考瞭如下內容 :
A)官方文檔 :http://oss.oetiker.ch/rrdtool/doc/index.en.html
B)abel 兄的大作 :http://bbs.chinaunix.net/viewthread.php?tid=552224&highlight=rrdtool
http://bbs.chinaunix.net/viewthread.php?tid=552220&highlight=rrdtool
作者 :ailms <ailms{@}263{dot}net>
版本 :v1
最後修改 :2006/11/17 17:35
**********************************************************************************************************************
一)前言
可能你已經頗不亟待的想知道如何往 RRD 文件插入數據、如何繪圖了吧?hoho,先別急,在你做這些事情之前,最好先思考以下幾個問題 :
A)如果給你一個 RRD 文件,你能知道它的第一次/最後一次 update 的時間是在什麼時候嗎?
B)如果你很久之前建立了一個 RRD 文件,現在因爲工作原因需要對該 RRD 文件進行一些修改。不過遺憾的是,
你已經不記得得當初設置的具體選項和參數了, 這時候該怎麼辦呢?
這兩個問題就對應今天要講的兩個操作 :first/last 、info
。
first 就是用於查看該 RRD 文件中某個 RRA 的第一個數據是在什麼時候插入的(或者說第一次更新);
last 就是查看該 RRD 文件的最近一次更新;
info就是查看 rrd 文件的結構信息。
下面就以實際例子來看一下該怎麼用這三個命令 :
二)如何查詢一個 RRD 文件的結構信息
CODE:
[root@dns1 bob]# rrdtool info eth0.rrd (由於輸出信息較多,截取了一部分)
filename = "eth0.rrd"
rrd_version = "0003"
step = 300 # RRDtool 希望每5分鐘收到一個數據
last_update = 1163862985 # 這是最近一次更新的 timestamp 。可以用 date 轉換爲具體的時間
ds[eth0_in].type = "COUNTER" # 有一個名爲 eth0_in 的 DS,DST是 COUNTER
ds[eth0_in].minimal_heartbeat = 600 # hearbeat 時間是600 秒
ds[eth0_in].min = 0.0000000000e+00 # eth0_in 的最小值是 0 (bytes)
ds[eth0_in].max = 1.2500000000e+07 # eth0_in 的最大值是
1250000000 (bytes)
ds[eth0_in].last_ds = "UNKN"
ds[eth0_in].value = 0.0000000000e+00
ds[eth0_in].unknown_sec = 85
ds[eth0_out].type = "COUNTER"
ds[eth0_out].minimal_heartbeat = 600
ds[eth0_out].min = 0.0000000000e+00
ds[eth0_out].max = 1.2500000000e+07
ds[eth0_out].last_ds = "UNKN"
ds[eth0_out].value = 0.0000000000e+00
ds[eth0_out].unknown_sec = 85
rra[0].cf = "AVERAGE" # 第一個 RRA 的編號是0,不是1。
rra[0].rows = 600 # 共保存 600 個記錄
rra[0].pdp_per_row = 1 # 每個 CDP 由一個 PDP 統計得出
rra[0].xff = 5.0000000000e-01 # 只要當前interval 的 PDP 爲 unknown ,則該
CDP 的值也是unknown
rra[0].cdp_prep[0].value = NaN
rra[0].cdp_prep[0].unknown_datapoints = 0
rra[0].cdp_prep[1].value = NaN
rra[0].cdp_prep[1].unknown_datapoints = 0
rra[1].cf = "AVERAGE" # 第二個 RRA 的編號是 1。同樣也是 AVERAGE 型。
rra[1].rows = 600 # 也是保存 600 個記錄
rra[1].pdp_per_row = 4 # 每個 CDP 由4個 PDP 的求平均值得出
rra[1].xff = 5.0000000000e-01 # 每個 CDP 最多允許2個 PDP 爲 unknown ,超過則該 CDP 爲unknown
rra[1].cdp_prep[0].value = NaN
rra[1].cdp_prep[0].unknown_datapoints = 3
rra[1].cdp_prep[1].value = NaN
rra[1].cdp_prep[1].unknown_datapoints = 3
[root@dns1 bob]#
由於信息太長,這裏截取了後面2個 RRA 的信息。
三)第一次更新/最近一次更新
如果想知道最近一次更新發生在什麼時候,除了可以用上面的 info 操作,還可以用 last 操作
CODE:
[root@dns1 bob]# rrdtool last eth0.rrd
1163862985
[root@dns1 bob]#
如果轉換成具體的時間就是 :
CODE:
[root@dns1 bob]# rrdtool last eth0.rrd |xargs -i date -d
'1970-01-01 {} sec utc'
六 11月 18
23:16:25 CST 2006
[root@dns1 bob]#
CODE:
[root@dns1 bob]# rrdtool first eth0.rrd
1163683200
[root@dns1 bob]#
如果換成具體的時間就是 :
CODE:
[root@dns1 bob]# [root@dns1 bob]# rrdtool first eth0.rrd
|xargs -i date -d '1970-01-01 {} sec
utc'
四 11月 16
21:20:00 CST 2006
[root@dns1 bob]#
這三個命令的語法都非常簡單,但並不可以因此小看它們的功能,尤其是 info 操作。日後如果需要對 RRD 文件進行調整,是經常需要用到的。
更新 RRD 文件
**********************************************************************************************************************
注 :該教程參考瞭如下內容 :
A)官方文檔 :http://oss.oetiker.ch/rrdtool/doc/index.en.html
B)abel 兄的大作 :http://bbs.chinaunix.net/viewthread.php?tid=552224&highlight=rrdtool
http://bbs.chinaunix.net/viewthread.php?tid=552220&highlight=rrdtool
作者 :ailms <ailms{@}263{dot}net>
版本 :v1
最後修改 :2006/11/17 17:35
**********************************************************************************************************************
一)前言
寫了N多東東,總算到了
update 部分了。這裏有必要比較一下 RRDtool 和
MRTG 在 update 方面的差別。
A)MRTG 可以通過 SNMP 協議直接訪問 SNMP 對象,你只需要在 cfg 文件中的 Target 指定 OID ,MRTG
就可以自動替你取回數據。
例如Target[as1_eth0]:
2:[email protected]:::::1 ,表示使用 SNMP v1 協議訪問 172.17.64.11 主機上 index 爲 2 的那個接口,
默認是取 ifInOctets 和
ifOutOctets 這兩個對象的值。RRDtool 則沒有這個功能,只能你自己寫腳本取數據。
B)MRTG 只支持 COUNTER 和 GAUGE 類型的 Target ;RRDtool
則還可以使用 DERIVE、ABSOLUTE、COMPUTE
C)由於上面的原因,MRTG 無法識別小數,負數。例如你給
MRTG 一個 -1 的值,它會解釋爲 1 ;這點可以通過 LOG 看出來。
小數也不行。例如 .72 (bc 的輸出)會被識別爲 72 ,而不是 0.72。
D)MRTG 每次 update 每次運行只更新一次,或者說只插入一行記錄。但 RRDtool 可以在一個 updat操作中插入多個記錄。
E)MRTG 一次要求2個值,RRDtool 則沒有該方面的限制。
F)最大的一個區別是, MRTG 在收到一個值後會自動得出
timestamp ,並記錄在 log 的第一個字段;而
RRDtool 是需要你給出一個 timestamp ,
表示該數據是什麼時間採集的。
二)update 操作的語法格式
CODE:
rrdtool {update | updatev} filename
[--template|-t ds-name[:ds-name]...]
N|timestamp:value[:value...]
at-timestamp@value[:value...]
[timestamp:value[:value...] ...]
N 表示 now 的意思,會被
RRDtool 替換爲當前的 timestamp ,也就是
date +%s 的結果。Timestamp 部分比較靈活,可以是數字形式,也可以是
AT-風格的時間(參考 at 命令的 manual),有點類似於自然語言的風格。
三)手工方式 update 數據庫
我們先學習一下如何手工 update 數據庫。Update 命令分成兩部分 :
A)時間戳 (timestamp):表示該數據是在那個時間點採集的。Timestamp 的格式可以非常靈活 :
數字形式 :例如1164419418 ,表示 “六 11月 25 09:50:18 CST 2006”。通常用於手工插入的方式。
快捷方式 :N 。字母N 表示當前時間(Now)。如果是通過 crontab 的方式來運行 update 操作,這是最實用的方式。
AT-風格 :所謂的 AT 風格的時間,可以參考 at 命令的 manual。例如
now、yesterday、now-1hour、now+5min 都是 AT風格的時間。
要注意的是,如果使用 AT風格的時間,則時間和第一個value之間使用 @ 分隔,而不是
“:”
B)數值部分 :一個 RRD 文件可以有多個 DS ,所以一次 update 可以給出多個 value 。多個 value 之間用 “:” 分隔。不過是不是所有的 DS 都必須
給出值呢?不一定。有時候你只想給出一部分 DS 的值,甚至有時候某些類型的 DS 是不允許賦值的,例如 COMPUTE 型的 DS 就是這樣一個例子。
四)實際操作
實例一 :一個錯誤的例子
CODE:
[root@dns1 bob]# rrdtool update eth0.rrd 1163862980:1:2
ERROR: illegal attempt to update using time 0 when last update time is
1163862985 (minimum one second step)
[root@dns1 bob]#
咦?爲什麼出錯了呢?是語法錯誤嗎?不是的,RRDtool 提示最近一次更新是在1163862985 這個時候。也就是說,update 給出的時間戳必須大於該值。
不能等於或者小於該時刻。因爲數據一旦插入到 RRA 中,就不允許再次修改。所以 update 會檢查給出的時間戳是否大於最後一次更新的時間戳,如果不是
則報錯,不予執行。那如何才能知道最近一次更新的時間戳呢?還記得前一篇“如何獲取RRD文件的信息”中介紹的
last 和 info 命令嗎?對了!就是它們。
執行一下看看是什麼結果 ?
CODE:
[root@dns1 bob]# rrdtool last eth0.rrd
1163862985
[root@dns1 bob]#
last 操作顯示的時間戳和上面的報錯信息給出的值一樣。這個時間是
CODE:
[root@dns1 bob]# date -d '1970-01-01 1163862985 sec utc'
六 11月 18
23:16:25 CST 2006
[root@dns1 bob]#
總之如果要 update 數據庫,則 update 操作給出的時間戳必須晚於最後一次 update 的時間。
實例二 :還是一個錯誤的例子
我們挑 23:16的下一個5分鐘23:20作爲時間戳吧。
CODE:
[root@dns1 bob]# date -d '2006-11-18 23:20' +%s
1163863200
[root@dns1 bob]#
所以 update 命令爲 :
CODE:
[root@dns1 bob]# rrdtool update eth0.rrd 1163863200:1
ERROR: expected 2 data source readings (got 1) from 1163863200:1:...
[root@dns1 bob]#
還是不行?!!
仔細看錯誤信息,原來是我們給少了一個值。還記得 info 命令嗎?這會兒它派上用場了。
CODE:
[root@dns1 bob]# rrdtool info eth0.rrd
filename = "eth0.rrd"
…..(省略)
last_update = 1163862985
ds[eth0_in].type = "COUNTER"
ds[eth0_out].type = "COUNTER"
原來是2個 DS ,怪不得 RRDtool 會報錯了
實例三 :這次應該成功了吧?
CODE:
[root@dns1 bob]# rrdtool update eth0.rrd 1163863200:1:2
[root@dns1 bob]#
這會倒是沒有錯誤信息,那究竟數據是否別插入到 RRA 中了呢?
對於該問題,有兩個方法,一個是通過 fetch 操作,從
RRA 中提取數據;但這個我們下一篇再講。
還有一種方法就是用 updatev 操作來代替 update 。updatev 的 v 表示
verbose 的意思,現在就來看 updatev 的作用 :
實例四 :updatev 的好處
我們執行多個 update 操作
CODE:
[root@dns1 bob]# rrdtool last eth0.rrd
1163864400
[root@dns1 bob]#
[root@dns1 bob]# rrdtool update eth0.rrd 1163864700:3000:4000
[root@dns1 bob]# rrdtool updatev eth0.rrd 1163865000:3300:4600
return_value = 0
[1163865000]RRA[AVERAGE][1]DS[eth0_in] = 1.0000000000e+00
[1163865000]RRA[AVERAGE][1]DS[eth0_out] = 2.0000000000e+00
可以看到 return value 是 0,這個 return value 你可以理解爲 shell 編程中的 exit status 。updatev用 0 表示成功,-1 表示失敗。
不過我們插入的值明明是 3300 和 4600 ,爲什麼出來的結果是 1和2 呢?
這是因爲 eth0_in 和 eth0_out 都是 COUNTER 型的 DS,所以
RRDtool 在收到 3300 和 4600 後,會作一個運算,就是
(3300-3000)/ step (300)= 1,(4600-4000)/step(300)=2 ,這就是 1和 2 這兩個值的來源了。還記得前面提到的 PDP 嗎?
這兩個值 (1 和2)就是 PDP 了,而不是 3300 和
4600 。這點要搞清楚。
實例五 :另外一個 updatev 的例子
CODE:
[root@dns1 bob]#
[root@dns1 bob]# rrdtool updatev eth0.rrd 1163865300:3300:4600
return_value = 0
[1163865300]RRA[AVERAGE][1]DS[eth0_in] = 0.0000000000e+00
[1163865300]RRA[AVERAGE][1]DS[eth0_out] = 0.0000000000e+00
[root@dns1 bob]#
在1163865300 這個時刻我們給出的值和上次一樣,所以 eth0_in 和 eth0_out 的 PDP 都爲 0
搞清楚了 PDP 的概念,現在我們來看什麼是 CDP ,以及 CDP 是如何計算的
實例六 :通過 updatev 掌握 CF 的概念
CODE:
[root@dns1 bob]# rrdtool updatev eth0.rrd
1163865600:4000:5000
return_value = 0
[1163865600]RRA[AVERAGE][1]DS[eth0_in] = 2.3333333333e+00
[1163865600]RRA[AVERAGE][1]DS[eth0_out] = 1.3333333333e+00
[1163865600]RRA[AVERAGE][4]DS[eth0_in] = 1.6666666667e+00
[1163865600]RRA[AVERAGE][4]DS[eth0_out] = 1.6666666667e+00
[1163865600]RRA[AVERAGE][24]DS[eth0_in] = NaN
[1163865600]RRA[AVERAGE][24]DS[eth0_out] = NaN
[root@dns1 bob]#
這次的輸出和上次又不一樣了。這次 update 操作影響到幾個 RRA ,看到 [] 中的 1,4,24 了嗎?它們就是代表不同的
RRA 中每個 CDP 所包含的 PDP 數量。
1 就是 1個 CDP 包含1 個 PDP,4 就是 一個 CDP 包含4個 PDP(20分鐘)、24 就是 一個 CDP 包含24個 PDP(2小時)。
不過爲什麼沒有 288 呢?eth0.rrd 的第4個 RRA 不是規定每288個 PDP 合併爲一個 CDP 嗎?
因爲這個時候還輪不到它出場。1163865600 / 7200 = 161648 , 也就是說剛好1163865600 是在 7200 的某個週期上(161648)。
但1163865600 / 86400 ≈ 13470.66 ,說明1163865600 還不到 86400 的週期。
必須等到13471* 86400=1163894400 纔會出現 [288] 的 CDP,那這個時間戳代表的時間是什麼時候呢?看下面的 date 命令就知道了 :
CODE:
[root@dns1 bob]# date -d '1970-01-01 1163894400 sec utc'
日 11月 19
08:00:00 CST 2006
[root@dns1 bob]#
[root@dns1 root]# date -d '1970-01-01 1163865600 sec utc'
日 11月 19 00:00:00 CST 2006
[root@dns1 root]#
這樣不就是剛好相差1天的時間了嗎?你可能會覺得很奇怪,爲什麼不是00:00 而是 08:00呢?
還記得create 操作的語法嗎?其中有一個 –-start 參數嗎?不記得了?沒關係,那就得用 first 操作來重新找出來,
CODE:
[root@dns1 bob]# rrdtool first eth0.rrd --rraindex 3
1100822400
[root@dns1 bob]#
[root@dns1 bob]# date -d '1970-01-01 1100822400 sec utc'
五 11月 19
08:00:00 CST 2004
[root@dns1 bob]#
看到了嗎?是 2004 年的 11
月19日早上8點正,距離 2006-11-19剛好是2年,也就是 730 天,因爲 eth0.rrd 的第4個RRA
只保存730個記錄。每個記錄時間上相差1天。也就是第一個記錄是 2004/11/19 8:00 ,第二個記錄是 2004/11/20 8:00 ,
第三個記錄代表 2004/11/21 8:00 ,依次類推。所以離1163865600 最近的下一個記錄是發生在 2006/11/19 8:00 。
所以嚴格意義上來說,RRDtool 中的一天並不一定是從
0:00 開始的,但可以保證的就是兩個記錄之間肯定相差86400秒(1天)。
四)自動更新數據庫
其實這些都只不過是手工 update 時需要注意的一些地方,如果是自動更新數據庫,時間戳方面就交給 RRDtool 去處理吧,我們不用操心了。
前面我們已經寫好了一個腳本,現在就用它來更新
CODE:
[root@dns1 bob]# cat get_eth0_traffic.sh
#!/bin/bash
# 首先取得 eth0 接口的
ifIndex
index=$(snmpwalk -IR localhost RFC1213-MIB::ifDescr |grep eth0|cut -d '=' -f
1|cut -d '.' -f 2)
# 再通過 snmp 協議取得 ififInOctets 和 ifOutOctets 的值
# 由於在 /etc/snmp.conf 中配置了
defVersion 和 defCommunity ,所以
snmpget 命令不用指定這兩個參數
eth0_in=$(snmpget -IR -Os localhost ifInOctets.${index}|cut -d ':' -f 2|tr -d
'[:blank:]')
eth0_out=$(snmpget -IR -Os localhost ifOutOctets.${index}|cut -d ':' -f 2 |tr
-d '[:blank:]')
echo ${eth0_in}
echo ${eth0_out}
# 需要我要用這些數據來更新 eth0.rrd ,注意
update 時的 timestamp 我們用的是 N
/usr/local/rrdtool-1.2.14/bin/rrdtool
updatev /home/bob/eth0.rrd N:${eth0_in}:${eth0_out}
[root@dns1 bob]#
五)接下來是什麼呢?
有了數據,下面該學什麼了呢?是繪圖嗎?
不是!^_^!! (估計有人快瘋了吧)
在繪圖之前,你有沒有想過 RRDtool 在繪圖時如何取數據的呢?
例如我想畫2小時內的數據,那麼我們有4個 RRA ,其 resolution 分別是 300,1200,7200,86400
(還記得什麼是 resolution 嗎?就是每個 RRA 中兩個 CDP 相隔的時間)。是從第一個 RRA 取出 7200/300=24 個記錄,
還是從第二個 RRA 取出 7200/1200=6 個記錄呢?或者是從第三個 RRA 中取出1個記錄就可以呢?
這些問題我們就留待下一篇再學習吧。這裏給大家留幾個問題 :
QUOTE:
A) 如果 eth0.rrd 在5分鐘內收到不止1個更新,結果會怎樣?提示:用 updatev 就可以看出來了B) 如果過了 eth0.rrd 在5分鐘內沒有收到腳本返回的值,是否立即就用 UNKNOWN 作爲 PDP 的值?
C) 參考上面的例子,搞清楚 heartbeat 的含義
D) 在搞清楚 heartbeat 後,再想一下 heartbeat 和 step 之間的關係。