RRDtool簡體中文教程 v1.01 – 3

rel="File-List" href="file:///C:%5CDOCUME%7E1%5Ccxgao%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml">

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 文件的結構信息

[Copy to clipboard]

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 DSDST 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 操作

[Copy to clipboard]

CODE:

[root@dns1 bob]# rrdtool last eth0.rrd
1163862985
[root@dns1 bob]#


如果轉換成具體的時間就是 :

[Copy to clipboard]

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]#



[Copy to clipboard]

CODE:

[root@dns1 bob]# rrdtool first eth0.rrd
1163683200
[root@dns1 bob]#


如果換成具體的時間就是 :

[Copy to clipboard]

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 則還可以使用 DERIVEABSOLUTECOMPUTE
  
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 操作的語法格式

[Copy to clipboard]

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。例如 nowyesterdaynow-1hournow+5min 都是 AT風格的時間。

                       
要注意的是,如果使用 AT風格的時間,則時間和第一個value之間使用 @ 分隔,而不是 “:”

B
)數值部分 :一個 RRD 文件可以有多個 DS ,所以一次 update 可以給出多個 value 。多個 value 之間用 “:” 分隔。不過是不是所有的 DS 都必須

   
給出值呢?不一定。有時候你只想給出一部分 DS 的值,甚至有時候某些類型的 DS 是不允許賦值的,例如 COMPUTE 型的 DS 就是這樣一個例子。
   

四)實際操作

實例一 :一個錯誤的例子

[Copy to clipboard]

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 命令嗎?對了!就是它們。

執行一下看看是什麼結果 ?

[Copy to clipboard]

CODE:

[root@dns1 bob]# rrdtool last eth0.rrd
1163862985
[root@dns1 bob]#


last
操作顯示的時間戳和上面的報錯信息給出的值一樣。這個時間是

[Copy to clipboard]

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作爲時間戳吧。

[Copy to clipboard]

CODE:

[root@dns1 bob]# date -d '2006-11-18 23:20' +%s
1163863200
[root@dns1 bob]#


所以 update 命令爲 :

[Copy to clipboard]

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 命令嗎?這會兒它派上用場了。

[Copy to clipboard]

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 會報錯了

實例三 :這次應該成功了吧?

[Copy to clipboard]

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 操作

[Copy to clipboard]

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 ,爲什麼出來的結果是 12 呢?

這是因爲 eth0_in eth0_out 都是 COUNTER 型的 DS,所以 RRDtool 在收到 3300 4600 後,會作一個運算,就是

3300-3000/ step 300= 1,(4600-4000/step300=2 ,這就是 1 2 這兩個值的來源了。還記得前面提到的 PDP 嗎?

這兩個值 (1 2)就是 PDP 了,而不是 3300 4600   。這點要搞清楚。


實例五 :另外一個 updatev 的例子

[Copy to clipboard]

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 的概念

[Copy to clipboard]

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 ,看到 [] 中的 1424 了嗎?它們就是代表不同的 RRA 中每個 CDP 所包含的 PDP 數量。

1
就是 1 CDP 包含1 PDP4 就是 一個 CDP 包含4 PDP20分鐘)、24 就是 一個 CDP 包含24 PDP2小時)。

不過爲什麼沒有 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 命令就知道了 :

[Copy to clipboard]

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 操作來重新找出來,

[Copy to clipboard]

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 的第4RRA

只保存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 去處理吧,我們不用操心了。

前面我們已經寫好了一個腳本,現在就用它來更新

[Copy to clipboard]

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 分別是 3001200720086400

(還記得什麼是 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 之間的關係。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章