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

  rel="File-List" href="file:///C:%5CDOCUME%7E1%5Ccxgao%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml">RRDtool簡體中文教程 v1.01 – 6

 

RRDtool簡體中文教程_9:如何使用RPN
如何使用RPN

**********************************************************************************************************************
注 :該教程參考瞭如下內容 :
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
**********************************************************************************************************************


一)前言

RPN
代表逆波蘭式(Reverse Polish Notation)。逆波蘭式最早於1920年由Jan Lukasiewicz 發明,最神奇的地方是用它來表示數學表達式,

完全不需要括號。而且 RPN 不像普通的數學表達式那樣,操作符在操作數的中間,而是在操作數的右邊。例如 3+2 RPN 表示就是 3,2,+

3+
2X5) 用 RPN 表示就是 3,2,5,x,+ 最後運算的部分(加法部分)的操作符放在最後,乘號放在前面,表示先執行 2 x 5 ,在把結果和3相加。

RRDtool 中,RPN 還可以用來表示 if-then-else 關係。這點在繪圖中很有用。例如你要看 eth0 接口在一天當中流量 ≥ 10Mb/s 的部分,隱藏

其他低於 10Mb/s 的部分,則可以用到這個功能。

二)操作符

什麼是 RPN

A
RPN Reverse Polish Notation 的縮寫,是用於表示算術運算和邏輯運算的一種語法格式。

B
RRDtool CDEF 語句中就經常使用 RPN 來對 DEF 取出來的數據進行運算。

C
RPN 的特點是操作數和操作符出現的順序和運算的順序一致,這樣就不需要使用括號了

D
RPN 的格式是 <value1>,<value2>,<operator> ,[<value1>,<value2>,<operator>]… 可以看出是操作數在前,操作符在後的格式

E
RPN 需要提到堆棧的概念(stack)。堆棧是用來存儲操作數和操作符的。

F
)當堆棧中壓入(push)一個操作符時,就從堆棧中取出(pop)所需要的操作數進行計算(根據操作的不同pop出不同數量的操作數)。
  
   
結果再返回(push)堆棧,最終整個 RPN 應該只返回一個值,或者說堆棧中只有一個元素

G
)在 CDEF 中書寫 RPN 操作符,要一律以大寫的格式出現

H
RPN 中,如果某個部分的運算結果非 0,則被認爲是 true ,只有 0 才被認爲是 false

三)RPN 操作符的分類

A
)布爾操作符 :GTGELTLEEQNE

B
)特殊值比較符 :UNISINF

C
)條件操作符 :IF

D
)比較操作符 :MINMAXLIMIT

E
)算術操作符 :+ -*/%SIN, COS, LOG, EXP, SQRTFLOOR, CEILATANATAN2DEG2RAD, RAD2DEG

F
)數據集操作符 :所謂數據集(sets),就是指多個數據。SORTREVAVGTREND

G
)特殊值 :UNKNINFNEINFPREVCOUNT

H
)時間操作符 :NOWTIMELTIME

I
)堆棧操作符 :POPDUPEXC

四)RPN 操作的結果

A
)布爾操作符 :從堆棧中 pop 出兩個元素,並根據比較結果返回 0 false) 或者 1 。任何同 UNKNOWN 或者 INF NEINF 比較的都爲 0

B
)特殊值比較符 :從堆棧中 pop 1個元素,並同 UNKNOWN 或者 INFNEINF 比較。結果爲 0 或者 1

C
)條件操作符 :從堆棧中pop3個元素,如果最後pop出的那個元素不爲0(條件部分爲 true),則第2 pop 出的那個元素被重新入棧(then部分);

   
否則第一次pop出的元素重新入棧(else部分)。結果爲 then 部分或者 else 部分返回的值,不一定爲0或者1

D
)比較操作符 :

   
對於 MIN/MAX 操作符來說,從堆棧中 pop 出兩個操作符,並把較大/小的那個重新入棧。如果其中有一個 unknown ,則結果爲 unknonw

   
對於 LIMIT 操作符來說,先從堆棧中 pop 2個操作數,作爲邊界的定義;再 pop 1個操作數,比較該操作數是否落在前面定義的範圍內。
   
   
如果是則把最後 pop 出的那個元素重新入棧;否則把 UNKN 值入棧;注意,是 UNKN ,不是 0

E
)算術操作符 :根據操作符 pop 出所需數量的操作數,並把算術運算的結果重新入棧

F
)數據集操作符 :

對於 SORTREV 來說,先從堆棧中 POP 出一個元素,該元素的值就是下面要 pop 出的元素的數量。然後對堆棧從上到下的若干個元素

由第一次 pop 的出的那個元素的值決定)進行排序/反向排序。結果再重新入棧。

注意 :由於堆棧的特點是後進先出,所以要操作的元素是從SORT操作符往左方向計數。例如v1,v2,v3,v4,3,SORT是對 v2~v4 排序,

        
不是對 v1~v3 排序。   這點在書寫 RPN 時要特別注意。

注意 :SORT 操作是最小值在堆棧的最頂部;REV 則相反,最小值是在堆棧的最頂部。

對於 AVG 操作來說,同樣是先 pop 1個元素,並按照指定的數量對後續的若干個操作數進行操作,但結果只有一個數值,併入棧。


G
)特殊值 :

UNKN
表示壓入一個 UNKN 值;INFNEINF 分別表示把 INFNEINF 值壓入堆棧

H
)時間操作符 :

TIME
返回當前所提取的記錄的 timestamp ,注意 TIME 直接返回當前記錄的 timestamp ,不用任何參數

NOW
返回當前時間,同樣 NOW 不用任何參數

I
)堆棧操作符 :

POP
:彈出堆棧的最頂部的那個元素

   EXC
:交換堆棧頂部的第一個和第二個元素的值

五)如何閱讀 RPN

A
)首先按照從左到右的順序,找出第一個 RPN 操作符,並根據上一節的內容,對相應的操作數進行操作

B
)操作結果分成兩種 :

如果是一個值,直接替換掉該部分 RPN

如果是多個值(數據集操作,但 AVG 操作只返回一個值),則結果可能爲多個數值。則把這若干個數值用 ‘,’ 隔開,替換原來那部分 RPN

C
)如此循環,一直到整個 RPN 只返回一個值爲止

六、RPN 實例

A
)布爾型操作符 :2,1,GE 表示 2>=1

B
)特殊值比較符 :mydata,UN 表示 mydata == UNKNOWN

C
)條件操作符 :mydata,UN,0,mydata,IF 表示如果 mydata 等於 UNKNOWN ,則返回 0;否則還是返回 mydata 本身

D
)比較操作符 :mydata,20,MAX 表示返回 mydata20 這兩個數值中較大的一個;alpha,0,100,LIMIT 表示測試 alpha 的值是否小於等於0,大於等於100

E
)算術操作符 :1,2,- 表示 1-2=-1

F
)數據集操作符 :

v1,v2,v3,v4,v5,4,SORT
表示對 v1~v4 進行正向排序,結果堆棧中還是有5個元素;

v1,v2,v3,v4,3,AVG,+,2,/
表示對 v4,v3,v2 進行求平均值,並把結果入棧。假設v2~v4的結果爲 k ,則爲 v1,k,+,2,/ 也就是返回 (v1+k)/2

G
)特殊值 :mydata,0,GT,UNKN,mydata,IF 表示如果 mydata 大於 0則返回 UNKNOWN ,否則還是 mydata

H
)時間操作符 : TIME,`date –d “2006-10-01 10:00” +%s`,GT,0,1,IF 表示如果當前記錄的採集時間是在 2006-10-01 10:00 之後就返回1,否則返回 0

I
)堆棧操作符 :POP 就立即彈出第一個元素


七)如何表示 ANDOR 關係

A
)我們知道 RPN 表達式的值除非0,否則都認爲是 true

B
)我們可以利用 加法操作和乘法操作來實現 OR AND 的邏輯關係;如果兩個 RPN 表達式的值相加不等於0,就一定爲 true

   
如果兩個 RPN 表達式的值相乘不等於0,就一定爲 true

C
AND 關係的例子 :例如要比較某個值(159)是否在特定範圍內可以用 :

15,10,GT,15,20,LT,*
,結果就是(15>10*15 < 20= 1 * 1 =1 ,所以爲 true

    9,10,GT,9,20,LT,*
,結果就是 (9 >10* 9 < 20= 0 * 1 =0 ,所以爲 false

D
OR 關係的例子:同上例如要比較某個值(7,15)小於10,或者大於20

    7,10,LT,7,20,GT,+
,結果爲 (7 < 10+ 7 > 20 = 1+0 = 1,所以爲 true

    15,10,LT,15,20,GT,+
,結果爲 ( 15 < 10) + ( 15 > 20) = 0 + 0 =0 ,所以爲 false

E
)不過使用 + 需要注意一個地方 :相加的雙方都必須是正數,否則可能出現問題,例如一個正數(-5true)和另外一個正數(5true)相加爲 0false

如果是按照 OR 的關係,應該是 true 的,但結果變成0false),所以在使用 + 來表示 OR 的關係時,要注意該問題

F
)使用 * 則沒有該問題了,正數 * 負數 = 負數 (true)。所以如果遇到 OR 關係的時候,可以轉換爲 AND 關係來計算。

   
例如要表達 (x < a) OR ( x > b) 的關係,可以改爲 (x >a) AND ( x < b ) ,訣竅就是把比較操作符調反方向,把 + 改爲 *

八)實例

實例1:例如要看 eth0的總流量,可以用如下的定義

[Copy to clipboard]

CODE:

DEF:value1=eth0.rrd:eth0_in:AVERAGE /
DEF:value2=eth0.rrd:eth0_out:AVERAGE /
CDEF:value3=value1,value2,+ /
AREA:value3#ff0000:”total”


實例2 :假設我們要把 eth0 lo 的流入流量相加,得出總的流入流量

[Copy to clipboard]

CODE:

DEF:value1=eth0.rrd:eth0_in:AVERAGE /
DEF:value2=lo.rrd:lo_out:AVERAGE /
CDEF:value3=value2,UN,0,value2,IF /
CDEF:value4=value1,value3,+ /
AREA:value4#00ff00:”total in”


由於 lo.rrd 一直沒有數據插入,所以一直都是 NaN ,如果直接把 value1 value2 相加,由於 value2 UNKNOWN

所以相加的結果也是 UNKNOWN 。圖表上將什麼都不顯示,所以需要對 value2 進行判斷,如果 value2 的值 UNKNOWN value2,UN),

則返回0,否則返回 value2 本身。然後把這個值賦予變量 value3 ,最後把 value1 value3 相加,才得出真正入流量

實例3 :只看 eth0 中流量大於 10Mb/s 的部分,其餘不看

[Copy to clipboard]

CODE:

DEF:value1=eth0.rrd:eth0_in:AVERAGE /
DEF:value2=eth0.rrd:eth0-_out:AVERAGE /
CDEF:value3=value1,1000000,GT,value1,UNKN,IF /
CDEF:value4=value2,1000000,GT,value2,UNKN,IF /
AREA:value3#00ff00:”traffic_in /> 10M//s” /
AREA:value4#ff0000:”traffic_out /> 10Mb//s”:STACK


實例4 :只繪製特定時間段(在 2006/11/29 10:30 ~ 2006/11/29 12:30)的數據

[Copy to clipboard]

CODE:

DEF:value1=eth0.rrd:eth0_in:AVERAGE /
DEF:value2=eth0.rrd:eth0_out:AVERAGE /
CDEF:value3=TIME,$(date –d ‘2006-11-29 10:30’ +%s),GT,TIME,$(date –d '2006-11-29 12:30' +%s),LT,*,value1,UNKN,IF /
CDEF:value4=TIME,$(date –d ‘2006-11-29 12:30’ +%s),GT,TIME,$(date –d '2006-11-29 13:30' +%s),LT,*,value2,UNKN,IF /
AREA:value3#00ff00:”traffic_in” /
AREA:value4#ff0000:”traffic_out”:STACK


九、完結

相信到目前爲止,大家對 RRDtool 的認識應該更深了吧。一定要多做實驗,這樣才能做到熟能生巧,靈活應用。

其實剩下的還有 xportdumprestoreresizetunerrdcgi 幾個操作沒講,而且有一些應用經驗方面的東西也沒有提到,

不過想要全部寫出來,可能太耗時間和精力了,這些東西足足寫了我2個星期才寫完。中間還要不斷的做實驗以驗證正確性,怕誤導了大家。

如果需要的話,可以自己下載官方文檔學習,或者能有熱心的朋友補充就更好了,^_^

十、 本人的一點學習體會

  
本人從開始看 RRDtool 官方文檔到開始寫這篇教程,差不多用了2個月。 RRDtool 比學習 MRTG 難多了,資料少,RRDtool 的中文資料目前就只有 abel

兄寫的那一篇教程,如果沒有實際的上機操作,是不可能看懂的,所以 abel 兄也特別交代這點。如果只一心想速成,到頭來反而吃虧的是自己。

sendmailbind 這些服務器的配置,隨便在 google 上都可以搜到一大把所謂的快速入門,很多人也都照着做了。但明明別人可以的,爲什麼輪到自己

卻失敗呢?相信這是很多人心中曾有的鬱悶經歷。其實歸根到底就是基礎的問題,再深入一些就是學習心態的問題。不積跬步,無以至千里;不積小流,無以成江海

配置一個服務器並不是照抄配置就可以的。環境的不同,需求的不同這些因素都要考慮在內。怎麼可能做到完全一樣呢?同一個語句換個環境可能就不行了。所以我很

少看那些所謂的快速入門,要麼看 manual ,要麼看書(說到這裏,感覺 O’Reilly 的書真是不錯!^_^),如果是象 RRDtool這種的,就只好看官方文檔了。

  
學習的同時也要注意選擇好的教材。有時候一本好書能帶給無窮的好處。這點在我第一次看 O’Reilly 的 《dns & bind 4th》就有感覺,老外的書很注重循序漸進,
  
通常他們都是從某個實際工作環境的一個小例子說起,逐步引入各個命令、配置語句。然後隨着需求的壯大,不斷引入新的內容,最後形成一個總體。這樣看完後會心中會

有一個整體的框架和概念。不象國內一些書,毫不顧及條理,一上來就講語法、命令,搞得讀者很快都沒有興趣。這樣的書可謂害人不淺。

同時也建議大家讀英文原版的書。爲什麼呢?雖然中文的看起來快一些,但學習不是競走比賽。不是比誰看的快,而是比誰學的牢。英文書的詞彙其實都是專業詞彙,

只要看多了,自然記住了。實在記不住,可以用金山詞霸等工具輔助。俺的英文水平只有二級,但並不妨礙我看書。況且看英文書,有一個英文中文的轉換的過程。就

是揣摩作者這句話的含義,或者說這句話應該如何翻譯好。有些人覺得這個沒有什麼,但我覺得這個過程是你弄清作者思想的重要步驟。在你不斷的揣摩中,可能會有不同

的理解,直到你認爲這是最正確的那一種解釋爲止。如果是看中文書,可能會由於惰性,比較容易就接受作者的想法,而失去這個主動我思考的過程。

  
一時有感而發,胡亂寫了一通,請各位朋友見諒了。

  
書山有路勤爲徑,學海無涯苦做舟!

願以該座右銘和各位有志於Linux的朋友一起共勉!

   2006/12/2 22
23
發佈了4 篇原創文章 · 獲贊 1 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章